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 "MEDCouplingMemArray.txx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "CellModel.hxx"
25 #include "VolSurfUser.txx"
26 #include "InterpolationUtils.hxx"
27 #include "PointLocatorAlgos.txx"
29 #include "SplitterTetra.hxx"
30 #include "DirectedBoundingBox.hxx"
31 #include "InterpKernelMeshQuality.hxx"
32 #include "InterpKernelCellSimplify.hxx"
33 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
34 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
35 #include "InterpKernelAutoPtr.hxx"
36 #include "InterpKernelGeo2DNode.hxx"
37 #include "InterpKernelGeo2DEdgeLin.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
48 using namespace ParaMEDMEM;
50 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
52 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 };
54 MEDCouplingUMesh *MEDCouplingUMesh::New()
56 return new MEDCouplingUMesh;
59 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
61 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
62 ret->setName(meshName);
63 ret->setMeshDimension(meshDim);
68 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
69 * between \a this and the new mesh.
70 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
71 * delete this mesh using decrRef() as it is no more needed.
73 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
79 * Returns a new MEDCouplingMesh which is a copy of \a this one.
80 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
81 * this mesh are shared by the new mesh.
82 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
83 * delete this mesh using decrRef() as it is no more needed.
85 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
87 return new MEDCouplingUMesh(*this,recDeepCpy);
90 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
94 ret+=_nodal_connec->getHeapMemorySize();
95 if(_nodal_connec_index)
96 ret+=_nodal_connec_index->getHeapMemorySize();
97 return MEDCouplingPointSet::getHeapMemorySize()+ret;
100 void MEDCouplingUMesh::updateTime() const
102 MEDCouplingPointSet::updateTime();
105 updateTimeWith(*_nodal_connec);
107 if(_nodal_connec_index)
109 updateTimeWith(*_nodal_connec_index);
113 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
118 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
119 * then \a this mesh is most probably is writable, exchangeable and available for most
120 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
121 * this method to check that all is in order with \a this mesh.
122 * \throw If the mesh dimension is not set.
123 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
124 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
125 * \throw If the connectivity data array has more than one component.
126 * \throw If the connectivity data array has a named component.
127 * \throw If the connectivity index data array has more than one component.
128 * \throw If the connectivity index data array has a named component.
130 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
133 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
135 MEDCouplingPointSet::checkCoherency();
136 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
138 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
140 std::ostringstream message;
141 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
142 throw INTERP_KERNEL::Exception(message.str().c_str());
147 if(_nodal_connec->getNumberOfComponents()!=1)
148 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
149 if(_nodal_connec->getInfoOnComponent(0)!="")
150 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
152 if(_nodal_connec_index)
154 if(_nodal_connec_index->getNumberOfComponents()!=1)
155 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
156 if(_nodal_connec_index->getInfoOnComponent(0)!="")
157 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
162 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
163 * then \a this mesh is most probably is writable, exchangeable and available for all
164 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
165 * method thoroughly checks the nodal connectivity.
166 * \param [in] eps - a not used parameter.
167 * \throw If the mesh dimension is not set.
168 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
169 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
170 * \throw If the connectivity data array has more than one component.
171 * \throw If the connectivity data array has a named component.
172 * \throw If the connectivity index data array has more than one component.
173 * \throw If the connectivity index data array has a named component.
174 * \throw If number of nodes defining an element does not correspond to the type of element.
175 * \throw If the nodal connectivity includes an invalid node id.
177 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
182 int meshDim=getMeshDimension();
183 int nbOfNodes=getNumberOfNodes();
184 int nbOfCells=getNumberOfCells();
185 const int *ptr=_nodal_connec->getConstPointer();
186 const int *ptrI=_nodal_connec_index->getConstPointer();
187 for(int i=0;i<nbOfCells;i++)
189 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
190 if((int)cm.getDimension()!=meshDim)
192 std::ostringstream oss;
193 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
194 throw INTERP_KERNEL::Exception(oss.str().c_str());
196 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
198 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
200 std::ostringstream oss;
201 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
202 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
203 throw INTERP_KERNEL::Exception(oss.str().c_str());
205 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
210 if(nodeId>=nbOfNodes)
212 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
213 throw INTERP_KERNEL::Exception(oss.str().c_str());
218 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
219 throw INTERP_KERNEL::Exception(oss.str().c_str());
223 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
225 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
226 throw INTERP_KERNEL::Exception(oss.str().c_str());
235 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
236 * then \a this mesh is most probably is writable, exchangeable and available for all
237 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
238 * \param [in] eps - a not used parameter.
239 * \throw If the mesh dimension is not set.
240 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
241 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
242 * \throw If the connectivity data array has more than one component.
243 * \throw If the connectivity data array has a named component.
244 * \throw If the connectivity index data array has more than one component.
245 * \throw If the connectivity index data array has a named component.
246 * \throw If number of nodes defining an element does not correspond to the type of element.
247 * \throw If the nodal connectivity includes an invalid node id.
249 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
251 checkCoherency1(eps);
255 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
256 * elements contained in the mesh. For more info on the mesh dimension see
257 * \ref MEDCouplingUMeshPage.
258 * \param [in] meshDim - a new mesh dimension.
259 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
261 void MEDCouplingUMesh::setMeshDimension(int meshDim)
263 if(meshDim<-1 || meshDim>3)
264 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
270 * Allocates memory to store given number of cells.
271 * \param [in] nbOfCells - number of cell \a this mesh will contain.
273 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
274 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
276 void MEDCouplingUMesh::allocateCells(int nbOfCells)
278 if(_nodal_connec_index)
280 _nodal_connec_index->decrRef();
284 _nodal_connec->decrRef();
286 _nodal_connec_index=DataArrayInt::New();
287 _nodal_connec_index->reserve(nbOfCells+1);
288 _nodal_connec_index->pushBackSilent(0);
289 _nodal_connec=DataArrayInt::New();
290 _nodal_connec->reserve(2*nbOfCells);
296 * Appends a cell to the connectivity array. For deeper understanding what is
297 * happening see \ref MEDCouplingUMeshNodalConnectivity.
298 * \param [in] type - type of cell to add.
299 * \param [in] size - number of nodes constituting this cell.
300 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
302 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
303 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
305 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
307 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
308 if(_nodal_connec_index==0)
309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
310 if((int)cm.getDimension()==_mesh_dim)
313 if(size!=(int)cm.getNumberOfNodes())
315 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
316 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
317 throw INTERP_KERNEL::Exception(oss.str().c_str());
319 int idx=_nodal_connec_index->back();
321 _nodal_connec_index->pushBackSilent(val);
322 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
327 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
328 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
329 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
330 throw INTERP_KERNEL::Exception(oss.str().c_str());
335 * Compacts data arrays to release unused memory. This method is to be called after
336 * finishing cell insertion using \a this->insertNextCell().
338 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
339 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
341 void MEDCouplingUMesh::finishInsertingCells()
343 _nodal_connec->pack();
344 _nodal_connec_index->pack();
345 _nodal_connec->declareAsNew();
346 _nodal_connec_index->declareAsNew();
351 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
352 * Useful for python users.
354 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
356 return new MEDCouplingUMeshCellIterator(this);
360 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
361 * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
362 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
363 * Useful for python users.
365 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
367 if(!checkConsecutiveCellTypes())
368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
369 return new MEDCouplingUMeshCellByTypeEntry(this);
373 * Returns a set of all cell types available in \a this mesh.
374 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
376 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
382 * This method is a method that compares 'this' and 'other'.
383 * This method compares \b all attributes, even names and component names.
385 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
388 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
389 std::ostringstream oss; oss.precision(15);
390 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
393 reason="mesh given in input is not castable in MEDCouplingUMesh !";
396 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
398 if(_mesh_dim!=otherC->_mesh_dim)
400 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
404 if(_types!=otherC->_types)
406 oss << "umesh geometric type mismatch :\nThis geometric types are :";
407 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
408 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
409 oss << "\nOther geometric types are :";
410 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
411 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
415 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
416 if(_nodal_connec==0 || otherC->_nodal_connec==0)
418 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
421 if(_nodal_connec!=otherC->_nodal_connec)
422 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
424 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
427 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
428 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
430 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
433 if(_nodal_connec_index!=otherC->_nodal_connec_index)
434 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
436 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
443 * Checks if data arrays of this mesh (node coordinates, nodal
444 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
446 * \param [in] other - the mesh to compare with.
447 * \param [in] prec - precision value used to compare node coordinates.
448 * \return bool - \a true if the two meshes are same.
450 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
452 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
455 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
457 if(_mesh_dim!=otherC->_mesh_dim)
459 if(_types!=otherC->_types)
461 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
462 if(_nodal_connec==0 || otherC->_nodal_connec==0)
464 if(_nodal_connec!=otherC->_nodal_connec)
465 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
467 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
468 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
470 if(_nodal_connec_index!=otherC->_nodal_connec_index)
471 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
477 * Checks if \a this and \a other meshes are geometrically equivalent, else an
478 * exception is thrown. The meshes are
479 * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
480 * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
481 * the \a other mesh (with use of a specified cell comparison technique). The mapping
482 * from \a other to \a this for nodes and cells is returned via out parameters.
483 * \param [in] other - the mesh to compare with.
484 * \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
485 * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
486 * \param [in] prec - the precision used to compare nodes of the two meshes.
487 * \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
488 * to delete this array using decrRef() as it is no more needed.
489 * \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
490 * to delete this array using decrRef() as it is no more needed.
491 * \throw If the two meshes do not match.
493 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
494 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
496 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
497 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
499 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
501 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
502 MEDCouplingMesh::checkFastEquivalWith(other,prec);
503 if(_types!=otherC->_types)
504 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
505 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
508 int oldNbOfNodes=getNumberOfNodes();
509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
512 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
513 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
514 if(pt!=da->getConstPointer()+da->getNbOfElems())
515 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
516 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
519 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
522 da=m->zipConnectivityTraducer(cellCompPol);
523 int nbCells=getNumberOfCells();
526 maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
527 pt=std::find_if(da->getConstPointer()+nbCells,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
528 if(pt!=da->getConstPointer()+da->getNbOfElems())
529 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(nbCells,da->getNbOfElems(),1);
531 nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
532 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
536 * Checks if \a this and \a other meshes are geometrically equivalent, else an
537 * exception is thrown. The meshes are considered equivalent if (1) they share one
538 * node coordinates array and (2) they contain the same cells (with use of a specified
539 * cell comparison technique). The mapping from cells of the \a other to ones of \a this
540 * is returned via an out parameter.
541 * \param [in] other - the mesh to compare with.
542 * \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
543 * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
544 * \param [in] prec - a not used parameter.
545 * \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
546 * to delete this array using decrRef() as it is no more needed.
547 * \throw If the two meshes do not match.
549 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
550 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
552 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
553 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
555 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
557 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
558 MEDCouplingMesh::checkFastEquivalWith(other,prec);
559 if(_types!=otherC->_types)
560 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
561 if(_coords!=otherC->_coords)
562 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
563 std::vector<const MEDCouplingUMesh *> ms(2);
566 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
568 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
569 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
570 if(pt!=da->getConstPointer()+da->getNbOfElems())
572 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
574 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
575 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
579 * Checks if \a this and \a other meshes are geometrically equivalent with high
580 * probability, else an exception is thrown. The meshes are considered equivalent if
581 * (1) meshes contain the same number of nodes and the same number of elements of the
582 * same types (2) three cells of the two meshes (first, last and middle) are based
583 * on coincident nodes (with a specified precision).
584 * \param [in] other - the mesh to compare with.
585 * \param [in] prec - the precision used to compare nodes of the two meshes.
586 * \throw If the two meshes do not match.
588 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
590 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
592 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
593 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
594 int nbOfCells=getNumberOfCells();
598 status&=areCellsFrom2MeshEqual(otherC,0,prec);
599 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
600 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
602 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
606 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
607 * cells each node belongs to.
608 * \warning For speed reasons, this method does not check if node ids in the nodal
609 * connectivity correspond to the size of node coordinates array.
610 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
611 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
612 * dividing cell ids in \a revNodal into groups each referring to one
613 * node. Its every element (except the last one) is an index pointing to the
614 * first id of a group of cells. For example cells sharing the node #1 are
615 * described by following range of indices:
616 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
617 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
618 * Number of cells sharing the *i*-th node is
619 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
620 * \throw If the coordinates array is not set.
621 * \throw If the nodal connectivity of cells is not defined.
623 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
624 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
626 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
629 int nbOfNodes=getNumberOfNodes();
630 int *revNodalIndxPtr=new int[nbOfNodes+1];
631 revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
632 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
633 const int *conn=_nodal_connec->getConstPointer();
634 const int *connIndex=_nodal_connec_index->getConstPointer();
635 int nbOfCells=getNumberOfCells();
636 int nbOfEltsInRevNodal=0;
637 for(int eltId=0;eltId<nbOfCells;eltId++)
639 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
640 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
641 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
642 if(*iter>=0)//for polyhedrons
644 nbOfEltsInRevNodal++;
645 revNodalIndxPtr[(*iter)+1]++;
648 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
649 int *revNodalPtr=new int[nbOfEltsInRevNodal];
650 revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
651 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
652 for(int eltId=0;eltId<nbOfCells;eltId++)
654 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
655 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
656 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
657 if(*iter>=0)//for polyhedrons
658 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
664 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
669 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
675 if(cm.getOrientationStatus(nb,conn1,conn2))
682 class MinusOneSonsGenerator
685 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
686 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
687 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
688 static const int DELTA=1;
690 const INTERP_KERNEL::CellModel& _cm;
693 class MinusOneSonsGeneratorBiQuadratic
696 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
697 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
698 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
699 static const int DELTA=1;
701 const INTERP_KERNEL::CellModel& _cm;
704 class MinusTwoSonsGenerator
707 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
708 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
709 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
710 static const int DELTA=2;
712 const INTERP_KERNEL::CellModel& _cm;
718 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
719 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
720 * describing correspondence between cells of \a this and the result meshes are
721 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
722 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
723 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
724 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
725 * \warning For speed reasons, this method does not check if node ids in the nodal
726 * connectivity correspond to the size of node coordinates array.
727 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
728 * to write this mesh to the MED file, its cells must be sorted using
729 * sortCellsInMEDFileFrmt().
730 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
731 * each cell of \a this mesh.
732 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
733 * dividing cell ids in \a desc into groups each referring to one
734 * cell of \a this mesh. Its every element (except the last one) is an index
735 * pointing to the first id of a group of cells. For example cells of the
736 * result mesh bounding the cell #1 of \a this mesh are described by following
738 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
739 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
740 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
741 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
742 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
743 * by each cell of the result mesh.
744 * \param [in,out] revDescIndx - the array, of length one more than number of cells
745 * in the result mesh,
746 * dividing cell ids in \a revDesc into groups each referring to one
747 * cell of the result mesh the same way as \a descIndx divides \a desc.
748 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
749 * delete this mesh using decrRef() as it is no more needed.
750 * \throw If the coordinates array is not set.
751 * \throw If the nodal connectivity of cells is node defined.
752 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
753 * revDescIndx == NULL.
755 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
756 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
757 * \sa buildDescendingConnectivity2()
759 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
761 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
765 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
766 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
767 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
768 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
769 * \sa MEDCouplingUMesh::buildDescendingConnectivity
771 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
774 if(getMeshDimension()!=3)
775 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
776 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
780 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
781 * this->getMeshDimension(), that bound cells of \a this mesh. In
782 * addition arrays describing correspondence between cells of \a this and the result
783 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
784 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
785 * mesh. This method differs from buildDescendingConnectivity() in that apart
786 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
787 * result meshes. So a positive id means that order of nodes in corresponding cells
788 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
789 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
790 * i.e. cell ids are one-based.
791 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
792 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
793 * \warning For speed reasons, this method does not check if node ids in the nodal
794 * connectivity correspond to the size of node coordinates array.
795 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
796 * to write this mesh to the MED file, its cells must be sorted using
797 * sortCellsInMEDFileFrmt().
798 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
799 * each cell of \a this mesh.
800 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
801 * dividing cell ids in \a desc into groups each referring to one
802 * cell of \a this mesh. Its every element (except the last one) is an index
803 * pointing to the first id of a group of cells. For example cells of the
804 * result mesh bounding the cell #1 of \a this mesh are described by following
806 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
807 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
808 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
809 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
810 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
811 * by each cell of the result mesh.
812 * \param [in,out] revDescIndx - the array, of length one more than number of cells
813 * in the result mesh,
814 * dividing cell ids in \a revDesc into groups each referring to one
815 * cell of the result mesh the same way as \a descIndx divides \a desc.
816 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
817 * shares the node coordinates array with \a this mesh. The caller is to
818 * delete this mesh using decrRef() as it is no more needed.
819 * \throw If the coordinates array is not set.
820 * \throw If the nodal connectivity of cells is node defined.
821 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
822 * revDescIndx == NULL.
824 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
825 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
826 * \sa buildDescendingConnectivity()
828 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
830 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
834 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
835 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
836 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
837 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
839 * \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
840 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841 * \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.
843 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
849 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
851 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
855 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
856 * 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,
857 * excluding a set of meshdim-1 cells in input descending connectivity.
858 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
859 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
860 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
862 * \param [in] desc descending connectivity array.
863 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
864 * \param [in] revDesc reverse descending connectivity array.
865 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
866 * \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
867 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
868 * \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.
870 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
871 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
873 if(!desc || !descIndx || !revDesc || !revDescIndx)
874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
875 const int *descPtr=desc->getConstPointer();
876 const int *descIPtr=descIndx->getConstPointer();
877 const int *revDescPtr=revDesc->getConstPointer();
878 const int *revDescIPtr=revDescIndx->getConstPointer();
880 int nbCells=descIndx->getNumberOfTuples()-1;
881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
883 int *out1Ptr=out1->getPointer();
885 out0->reserve(desc->getNumberOfTuples());
886 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
888 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
890 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
892 out0->insertAtTheEnd(s.begin(),s.end());
894 *out1Ptr=out0->getNumberOfTuples();
896 neighbors=out0.retn();
897 neighborsIndx=out1.retn();
903 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
904 * For speed reasons no check of this will be done.
906 template<class SonsGenerator>
907 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
909 if(!desc || !descIndx || !revDesc || !revDescIndx)
910 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
911 checkConnectivityFullyDefined();
912 int nbOfCells=getNumberOfCells();
913 int nbOfNodes=getNumberOfNodes();
914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
915 int *revNodalIndxPtr=revNodalIndx->getPointer();
916 const int *conn=_nodal_connec->getConstPointer();
917 const int *connIndex=_nodal_connec_index->getConstPointer();
918 std::string name="Mesh constituent of "; name+=getName();
919 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
920 ret->setCoords(getCoords());
921 ret->allocateCells(2*nbOfCells);
922 descIndx->alloc(nbOfCells+1,1);
923 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
924 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
925 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
927 int pos=connIndex[eltId];
928 int posP1=connIndex[eltId+1];
929 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
930 SonsGenerator sg(cm);
931 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
932 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
933 for(unsigned i=0;i<nbOfSons;i++)
935 INTERP_KERNEL::NormalizedCellType cmsId;
936 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
937 for(unsigned k=0;k<nbOfNodesSon;k++)
939 revNodalIndxPtr[tmp[k]+1]++;
940 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
941 revDesc2->pushBackSilent(eltId);
943 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
945 int nbOfCellsM1=ret->getNumberOfCells();
946 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
948 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
949 int *revNodalPtr=revNodal->getPointer();
950 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
951 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
952 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
954 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
955 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
956 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
957 if(*iter>=0)//for polyhedrons
958 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
961 DataArrayInt *commonCells=0,*commonCellsI=0;
962 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
964 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
965 int newNbOfCellsM1=-1;
966 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
967 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
968 std::vector<bool> isImpacted(nbOfCellsM1,false);
969 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
970 for(int work2=work[0];work2!=work[1];work2++)
971 isImpacted[commonCellsPtr[work2]]=true;
972 const int *o2nM1Ptr=o2nM1->getConstPointer();
973 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
974 const int *n2oM1Ptr=n2oM1->getConstPointer();
975 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
976 ret2->copyTinyInfoFrom(this);
977 desc->alloc(descIndx->back(),1);
978 int *descPtr=desc->getPointer();
979 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
980 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
983 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
986 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
988 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
989 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
992 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
995 revDesc->reserve(newNbOfCellsM1);
996 revDescIndx->alloc(newNbOfCellsM1+1,1);
997 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
998 const int *revDesc2Ptr=revDesc2->getConstPointer();
999 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1001 int oldCellIdM1=n2oM1Ptr[i];
1002 if(!isImpacted[oldCellIdM1])
1004 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1005 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1009 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1010 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1011 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1019 struct MEDCouplingAccVisit
1021 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1022 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1023 int _new_nb_of_nodes;
1029 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1030 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1031 * array of cell ids. Pay attention that after conversion all algorithms work slower
1032 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1033 * conversion due presence of invalid ids in the array of cells to convert, as a
1034 * result \a this mesh contains some already converted elements. In this case the 2D
1035 * mesh remains valid but 3D mesh becomes \b inconsistent!
1036 * \warning This method can significantly modify the order of geometric types in \a this,
1037 * hence, to write this mesh to the MED file, its cells must be sorted using
1038 * sortCellsInMEDFileFrmt().
1039 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1040 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1041 * cellIdsToConvertBg.
1042 * \throw If the coordinates array is not set.
1043 * \throw If the nodal connectivity of cells is node defined.
1044 * \throw If dimension of \a this mesh is not either 2 or 3.
1046 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1047 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1049 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1051 checkFullyDefined();
1052 int dim=getMeshDimension();
1054 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1055 int nbOfCells=getNumberOfCells();
1058 const int *connIndex=_nodal_connec_index->getConstPointer();
1059 int *conn=_nodal_connec->getPointer();
1060 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1062 if(*iter>=0 && *iter<nbOfCells)
1064 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1066 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1068 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1072 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1073 oss << " in range [0," << nbOfCells << ") !";
1074 throw INTERP_KERNEL::Exception(oss.str().c_str());
1080 int *connIndex=_nodal_connec_index->getPointer();
1081 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1082 const int *connOld=_nodal_connec->getConstPointer();
1083 int connOldLgth=_nodal_connec->getNbOfElems();
1084 std::vector<int> connNew(connOld,connOld+connOldLgth);
1085 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1087 if(*iter>=0 && *iter<nbOfCells)
1089 int pos=connIndex[*iter];
1090 int posP1=connIndex[(*iter)+1];
1091 int lgthOld=posP1-pos-1;
1092 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1093 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1094 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1095 int *tmp=new int[nbOfFaces*lgthOld];
1097 for(int j=0;j<(int)nbOfFaces;j++)
1099 INTERP_KERNEL::NormalizedCellType type;
1100 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1104 std::size_t newLgth=std::distance(tmp,work)-1;
1105 std::size_t delta=newLgth-lgthOld;
1106 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1107 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1108 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1113 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1114 oss << " in range [0," << nbOfCells << ") !";
1115 throw INTERP_KERNEL::Exception(oss.str().c_str());
1118 _nodal_connec->alloc((int)connNew.size(),1);
1119 int *newConnPtr=_nodal_connec->getPointer();
1120 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1126 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1127 * polyhedrons (if \a this is a 3D mesh).
1128 * \warning As this method is purely for user-friendliness and no optimization is
1129 * done to avoid construction of a useless vector, this method can be costly
1131 * \throw If the coordinates array is not set.
1132 * \throw If the nodal connectivity of cells is node defined.
1133 * \throw If dimension of \a this mesh is not either 2 or 3.
1135 void MEDCouplingUMesh::convertAllToPoly()
1137 int nbOfCells=getNumberOfCells();
1138 std::vector<int> cellIds(nbOfCells);
1139 for(int i=0;i<nbOfCells;i++)
1141 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1145 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1146 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1147 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1148 * base facet of the volume and the second half of nodes describes an opposite facet
1149 * having the same number of nodes as the base one. This method converts such
1150 * connectivity to a valid polyhedral format where connectivity of each facet is
1151 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1152 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1153 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1154 * a correct orientation of the first facet of a polyhedron, else orientation of a
1155 * corrected cell is reverse.<br>
1156 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1157 * it releases the user from boring description of polyhedra connectivity in the valid
1159 * \throw If \a this->getMeshDimension() != 3.
1160 * \throw If \a this->getSpaceDimension() != 3.
1161 * \throw If the nodal connectivity of cells is not defined.
1162 * \throw If the coordinates array is not set.
1163 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1164 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1166 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1167 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1169 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1171 checkFullyDefined();
1172 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1173 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1174 int nbOfCells=getNumberOfCells();
1175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1176 newCi->alloc(nbOfCells+1,1);
1177 int *newci=newCi->getPointer();
1178 const int *ci=_nodal_connec_index->getConstPointer();
1179 const int *c=_nodal_connec->getConstPointer();
1181 for(int i=0;i<nbOfCells;i++)
1183 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1184 if(type==INTERP_KERNEL::NORM_POLYHED)
1186 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1188 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1189 throw INTERP_KERNEL::Exception(oss.str().c_str());
1191 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1194 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 !";
1195 throw INTERP_KERNEL::Exception(oss.str().c_str());
1198 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)
1201 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1203 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1204 newC->alloc(newci[nbOfCells],1);
1205 int *newc=newC->getPointer();
1206 for(int i=0;i<nbOfCells;i++)
1208 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1209 if(type==INTERP_KERNEL::NORM_POLYHED)
1211 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1212 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1214 for(std::size_t j=0;j<n1;j++)
1216 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1218 newc[n1+5*j+1]=c[ci[i]+1+j];
1219 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1220 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1221 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1226 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1228 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1229 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1234 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1235 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1236 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1237 * to write this mesh to the MED file, its cells must be sorted using
1238 * sortCellsInMEDFileFrmt().
1239 * \return \c true if at least one cell has been converted, \c false else. In the
1240 * last case the nodal connectivity remains unchanged.
1241 * \throw If the coordinates array is not set.
1242 * \throw If the nodal connectivity of cells is not defined.
1243 * \throw If \a this->getMeshDimension() < 0.
1245 bool MEDCouplingUMesh::unPolyze()
1247 checkFullyDefined();
1248 int mdim=getMeshDimension();
1250 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1253 int nbOfCells=getNumberOfCells();
1256 int initMeshLgth=getMeshLength();
1257 int *conn=_nodal_connec->getPointer();
1258 int *index=_nodal_connec_index->getPointer();
1263 for(int i=0;i<nbOfCells;i++)
1265 lgthOfCurCell=index[i+1]-posOfCurCell;
1266 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1267 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1268 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1272 switch(cm.getDimension())
1276 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1277 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1278 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1283 int nbOfFaces,lgthOfPolyhConn;
1284 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1285 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1290 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1294 ret=ret || (newType!=type);
1295 conn[newPos]=newType;
1297 posOfCurCell=index[i+1];
1302 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1303 newPos+=lgthOfCurCell;
1304 posOfCurCell+=lgthOfCurCell;
1308 if(newPos!=initMeshLgth)
1309 _nodal_connec->reAlloc(newPos);
1316 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1317 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1318 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1320 * \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
1323 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1325 checkFullyDefined();
1326 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1327 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1328 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1329 coords->recenterForMaxPrecision(eps);
1331 int nbOfCells=getNumberOfCells();
1332 const int *conn=_nodal_connec->getConstPointer();
1333 const int *index=_nodal_connec_index->getConstPointer();
1334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1335 connINew->alloc(nbOfCells+1,1);
1336 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1339 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1341 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1343 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1347 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1348 *connINewPtr=connNew->getNumberOfTuples();
1351 setConnectivity(connNew,connINew,false);
1355 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1356 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1357 * the format of returned DataArrayInt instance.
1359 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1360 * \sa MEDCouplingUMesh::getNodeIdsInUse
1362 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1364 checkConnectivityFullyDefined();
1365 int nbOfCells=getNumberOfCells();
1366 const int *connIndex=_nodal_connec_index->getConstPointer();
1367 const int *conn=_nodal_connec->getConstPointer();
1368 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1369 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1370 std::vector<bool> retS(maxElt,false);
1371 for(int i=0;i<nbOfCells;i++)
1372 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1376 for(int i=0;i<maxElt;i++)
1379 DataArrayInt *ret=DataArrayInt::New();
1381 int *retPtr=ret->getPointer();
1382 for(int i=0;i<maxElt;i++)
1389 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1390 * \sa MEDCouplingUMesh::getNodeIdsInUse
1392 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1394 int nbOfNodes=(int)nodeIdsInUse.size();
1395 int nbOfCells=getNumberOfCells();
1396 const int *connIndex=_nodal_connec_index->getConstPointer();
1397 const int *conn=_nodal_connec->getConstPointer();
1398 for(int i=0;i<nbOfCells;i++)
1399 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1402 if(conn[j]<nbOfNodes)
1403 nodeIdsInUse[conn[j]]=true;
1406 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1407 throw INTERP_KERNEL::Exception(oss.str().c_str());
1413 * Finds nodes not used in any cell and returns an array giving a new id to every node
1414 * by excluding the unused nodes, for which the array holds -1. The result array is
1415 * a mapping in "Old to New" mode.
1416 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1417 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1418 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1419 * if the node is unused or a new id else. The caller is to delete this
1420 * array using decrRef() as it is no more needed.
1421 * \throw If the coordinates array is not set.
1422 * \throw If the nodal connectivity of cells is not defined.
1423 * \throw If the nodal connectivity includes an invalid id.
1425 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1426 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1427 * \sa computeNodeIdsAlg()
1429 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1432 int nbOfNodes=getNumberOfNodes();
1433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1434 ret->alloc(nbOfNodes,1);
1435 int *traducer=ret->getPointer();
1436 std::fill(traducer,traducer+nbOfNodes,-1);
1437 int nbOfCells=getNumberOfCells();
1438 const int *connIndex=_nodal_connec_index->getConstPointer();
1439 const int *conn=_nodal_connec->getConstPointer();
1440 for(int i=0;i<nbOfCells;i++)
1441 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1444 if(conn[j]<nbOfNodes)
1445 traducer[conn[j]]=1;
1448 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1449 throw INTERP_KERNEL::Exception(oss.str().c_str());
1452 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1453 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1458 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1459 * For each cell in \b this the number of nodes constituting cell is computed.
1460 * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1461 * For polyhedrons, the face separation (-1) are excluded from the couting.
1463 * \return a newly allocated array
1465 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1467 checkConnectivityFullyDefined();
1468 int nbOfCells=getNumberOfCells();
1469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1470 ret->alloc(nbOfCells,1);
1471 int *retPtr=ret->getPointer();
1472 const int *conn=getNodalConnectivity()->getConstPointer();
1473 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1474 for(int i=0;i<nbOfCells;i++,retPtr++)
1476 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1477 *retPtr=connI[i+1]-connI[i]-1;
1479 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1485 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1486 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1487 * array mean that the corresponding old node is no more used.
1488 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1489 * this->getNumberOfNodes() before call of this method. The caller is to
1490 * delete this array using decrRef() as it is no more needed.
1491 * \throw If the coordinates array is not set.
1492 * \throw If the nodal connectivity of cells is not defined.
1493 * \throw If the nodal connectivity includes an invalid id.
1495 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1496 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1498 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1500 int newNbOfNodes=-1;
1501 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1502 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1507 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1508 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1510 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1515 return AreCellsEqual0(conn,connI,cell1,cell2);
1517 return AreCellsEqual1(conn,connI,cell1,cell2);
1519 return AreCellsEqual2(conn,connI,cell1,cell2);
1521 return AreCellsEqual3(conn,connI,cell1,cell2);
1523 return AreCellsEqual7(conn,connI,cell1,cell2);
1525 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1529 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1531 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1533 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1534 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1539 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1541 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1543 int sz=connI[cell1+1]-connI[cell1];
1544 if(sz==connI[cell2+1]-connI[cell2])
1546 if(conn[connI[cell1]]==conn[connI[cell2]])
1548 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1549 unsigned dim=cm.getDimension();
1555 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1556 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1557 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1558 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1559 return work!=tmp+sz1?1:0;
1562 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1565 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1572 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1574 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1576 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1578 if(conn[connI[cell1]]==conn[connI[cell2]])
1580 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1581 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1589 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1591 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1593 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1595 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1596 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1603 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1605 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1607 int sz=connI[cell1+1]-connI[cell1];
1608 if(sz==connI[cell2+1]-connI[cell2])
1610 if(conn[connI[cell1]]==conn[connI[cell2]])
1612 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1613 unsigned dim=cm.getDimension();
1619 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1620 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1621 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1622 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1627 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1628 std::reverse_iterator<int *> it2((int *)tmp);
1629 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1635 return work!=tmp+sz1?1:0;
1638 {//case of SEG2 and SEG3
1639 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1641 if(!cm.isQuadratic())
1643 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1644 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1645 if(std::equal(it1,it2,conn+connI[cell2]+1))
1651 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])
1658 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1666 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1667 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1669 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1671 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1673 std::vector<int> c1,c2;
1674 getNodeIdsOfCell(cellId,c1);
1675 other->getNodeIdsOfCell(cellId,c2);
1676 std::size_t sz=c1.size();
1679 for(std::size_t i=0;i<sz;i++)
1681 std::vector<double> n1,n2;
1682 getCoordinatesOfNode(c1[0],n1);
1683 other->getCoordinatesOfNode(c2[0],n2);
1684 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1685 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1686 if(*std::max_element(n1.begin(),n1.end())>prec)
1693 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1694 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1695 * and result remains unchanged.
1696 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1697 * If in 'candidates' pool -1 value is considered as an empty value.
1698 * WARNING this method returns only ONE set of result !
1700 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1702 if(candidates.size()<1)
1705 std::vector<int>::const_iterator iter=candidates.begin();
1706 int start=(*iter++);
1707 for(;iter!=candidates.end();iter++)
1709 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1714 result->pushBackSilent(start);
1718 result->pushBackSilent(*iter);
1720 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1727 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1728 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1730 * \param [in] compType input specifying the technique used to compare cells each other.
1731 * - 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.
1732 * - 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)
1733 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1734 * - 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
1735 * can be used for users not sensitive to orientation of cell
1736 * \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.
1737 * \param [out] commonCells
1738 * \param [out] commonCellsI
1739 * \return the correspondance array old to new in a newly allocated array.
1742 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1744 checkConnectivityFullyDefined();
1745 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1746 getReverseNodalConnectivity(revNodal,revNodalI);
1747 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1750 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1751 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1754 int nbOfCells=nodalI->getNumberOfTuples()-1;
1755 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1756 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1757 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1758 std::vector<bool> isFetched(nbOfCells,false);
1761 for(int i=0;i<nbOfCells;i++)
1765 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1766 std::vector<int> v,v2;
1767 if(connOfNode!=connPtr+connIPtr[i+1])
1769 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1770 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1773 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1777 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1778 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1779 v2.resize(std::distance(v2.begin(),it));
1783 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1785 int pos=commonCellsI->back();
1786 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1787 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1788 isFetched[*it]=true;
1796 for(int i=startCellId;i<nbOfCells;i++)
1800 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1801 std::vector<int> v,v2;
1802 if(connOfNode!=connPtr+connIPtr[i+1])
1804 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1807 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1811 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1812 v2.resize(std::distance(v2.begin(),it));
1816 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1818 int pos=commonCellsI->back();
1819 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1820 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1821 isFetched[*it]=true;
1827 commonCellsArr=commonCells.retn();
1828 commonCellsIArr=commonCellsI.retn();
1832 * Removes duplicates of cells from \a this mesh and returns an array mapping between
1833 * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1834 * equal cells found.
1835 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1836 * to write this mesh to the MED file, its cells must be sorted using
1837 * sortCellsInMEDFileFrmt().
1838 * \param [in] compType - specifies a cell comparison technique. Meaning of its
1839 * valid values [0,1,2] is as follows.
1840 * - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1841 * connectivity and type. This is the strongest policy.
1842 * - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1843 * are based on same nodes and have the same type and orientation.
1844 * - 2 : "nodal". Two cells are considered equal \c iff they
1845 * are based on same nodes and have the same type. This is the weakest
1846 * policy, it can be used by users not sensitive to cell orientation.
1847 * \param [in] startCellId - specifies the cell id at which search for equal cells
1848 * starts. By default it is 0, which means that all cells in \a this will be
1850 * \return DataArrayInt - a new instance of DataArrayInt, of length \a
1851 * this->getNumberOfCells() before call of this method. The caller is to
1852 * delete this array using decrRef() as it is no more needed.
1853 * \throw If the coordinates array is not set.
1854 * \throw If the nodal connectivity of cells is not defined.
1855 * \throw If the nodal connectivity includes an invalid id.
1857 * \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1858 * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1860 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1862 DataArrayInt *commonCells=0,*commonCellsI=0;
1863 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1865 int newNbOfCells=-1;
1866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1867 commonCellsI->end(),newNbOfCells);
1868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1869 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1870 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1875 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1876 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1877 * than \a other->getNumberOfCells() in the returned array means that there is no
1878 * corresponding cell in \a this mesh.
1879 * It is expected that \a this and \a other meshes share the same node coordinates
1880 * array, if it is not so an exception is thrown.
1881 * \param [in] other - the mesh to compare with.
1882 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1883 * valid values [0,1,2], see zipConnectivityTraducer().
1884 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1885 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1886 * values. The caller is to delete this array using
1887 * decrRef() as it is no more needed.
1888 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1891 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1892 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1893 * \sa checkDeepEquivalOnSameNodesWith()
1894 * \sa checkGeoEquivalWith()
1896 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1898 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1899 int nbOfCells=getNumberOfCells();
1900 static const int possibleCompType[]={0,1,2};
1901 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1903 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1904 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1906 throw INTERP_KERNEL::Exception(oss.str().c_str());
1908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1909 arr=o2n->substr(nbOfCells);
1910 arr->setName(other->getName());
1912 if(other->getNumberOfCells()==0)
1914 return arr->getMaxValue(tmp)<nbOfCells;
1918 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1919 * This method tries to determine if \b other is fully included in \b this.
1920 * The main difference is that this method is not expected to throw exception.
1921 * This method has two outputs :
1923 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1924 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1926 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1928 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1929 DataArrayInt *commonCells=0,*commonCellsI=0;
1930 int thisNbCells=getNumberOfCells();
1931 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1933 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1934 int otherNbCells=other->getNumberOfCells();
1935 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1936 arr2->alloc(otherNbCells,1);
1937 arr2->fillWithZero();
1938 int *arr2Ptr=arr2->getPointer();
1939 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1940 for(int i=0;i<nbOfCommon;i++)
1942 int start=commonCellsPtr[commonCellsIPtr[i]];
1943 if(start<thisNbCells)
1945 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1947 int sig=commonCellsPtr[j]>0?1:-1;
1948 int val=std::abs(commonCellsPtr[j])-1;
1949 if(val>=thisNbCells)
1950 arr2Ptr[val-thisNbCells]=sig*(start+1);
1954 arr2->setName(other->getName());
1955 if(arr2->presenceOfValue(0))
1962 * Merges nodes equal within \a precision and returns an array describing the
1963 * permutation used to remove duplicate nodes.
1964 * \param [in] precision - minimal absolute distance between two nodes at which they are
1965 * considered not coincident.
1966 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1967 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1968 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1969 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1970 * is to delete this array using decrRef() as it is no more needed.
1971 * \throw If the coordinates array is not set.
1972 * \throw If the nodal connectivity of cells is not defined.
1974 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1975 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1977 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1979 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1981 renumberNodes(ret->getConstPointer(),newNbOfNodes);
1987 * Merges nodes equal within \a precision and returns an array describing the
1988 * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1989 * of merged nodes is changed to be at their barycenter.
1990 * \param [in] precision - minimal absolute distance between two nodes at which they are
1991 * considered not coincident.
1992 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1993 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1994 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1995 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1996 * is to delete this array using decrRef() as it is no more needed.
1997 * \throw If the coordinates array is not set.
1998 * \throw If the nodal connectivity of cells is not defined.
2000 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
2001 * \ref py_mcumesh_mergeNodes "Here is a Python example".
2003 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
2005 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2007 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
2012 * Substitutes node coordinates array of \a this mesh with that of \a other mesh
2013 * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
2014 * meshes match with a specified precision, else an exception is thrown and \a this
2015 * remains unchanged. In case of success the nodal connectivity of \a this mesh
2016 * is permuted according to new order of nodes.
2017 * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
2018 * coordinates (and so more expensive) than simple equality.
2019 * \param [in] other - the other mesh whose node coordinates array will be used by
2020 * \a this mesh in case of their equality.
2021 * \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
2022 * \throw If the coordinates array of \a this is not set.
2023 * \throw If the coordinates array of \a other is not set.
2024 * \throw If the coordinates of \a this and \a other do not match.
2026 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
2028 const DataArrayDouble *coords=other.getCoords();
2030 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
2032 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
2033 int otherNbOfNodes=other.getNumberOfNodes();
2034 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
2036 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
2037 setCoords(newCoords);
2038 bool areNodesMerged;
2040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
2043 setCoords(oldCoords);
2044 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
2046 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
2047 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
2048 if(pt!=da->getConstPointer()+da->getNbOfElems())
2050 setCoords(oldCoords);
2051 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
2053 setCoords(oldCoords);
2054 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
2059 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2060 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2061 * cellIds is not given explicitely but by a range python like.
2063 * \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.
2064 * \return a newly allocated
2066 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2067 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2069 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
2071 if(getMeshDimension()!=-1)
2073 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
2080 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2082 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2084 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2086 return const_cast<MEDCouplingUMesh *>(this);
2091 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2092 * The result mesh shares or not the node coordinates array with \a this mesh depending
2093 * on \a keepCoords parameter.
2094 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2095 * to write this mesh to the MED file, its cells must be sorted using
2096 * sortCellsInMEDFileFrmt().
2097 * \param [in] begin - an array of cell ids to include to the new mesh.
2098 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2099 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2100 * array of \a this mesh, else "free" nodes are removed from the result mesh
2101 * by calling zipCoords().
2102 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2103 * to delete this mesh using decrRef() as it is no more needed.
2104 * \throw If the coordinates array is not set.
2105 * \throw If the nodal connectivity of cells is not defined.
2106 * \throw If any cell id in the array \a begin is not valid.
2108 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2109 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2111 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2113 if(getMeshDimension()!=-1)
2115 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
2123 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2125 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2127 return const_cast<MEDCouplingUMesh *>(this);
2132 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2134 * 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.
2135 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2136 * The number of cells of \b this will remain the same with this method.
2138 * \param [in] begin begin of cell ids (included) of cells in this to assign
2139 * \param [in] end end of cell ids (excluded) of cells in this to assign
2140 * \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).
2141 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2143 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2145 checkConnectivityFullyDefined();
2146 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2147 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2148 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2149 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2151 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2152 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2153 throw INTERP_KERNEL::Exception(oss.str().c_str());
2155 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2156 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2158 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2159 throw INTERP_KERNEL::Exception(oss.str().c_str());
2161 int nbOfCells=getNumberOfCells();
2162 bool easyAssign=true;
2163 const int *connI=_nodal_connec_index->getConstPointer();
2164 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2165 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2167 if(*it>=0 && *it<nbOfCells)
2169 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2173 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2174 throw INTERP_KERNEL::Exception(oss.str().c_str());
2179 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2184 DataArrayInt *arrOut=0,*arrIOut=0;
2185 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2188 setConnectivity(arrOut,arrIOut,true);
2192 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2194 checkConnectivityFullyDefined();
2195 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2196 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2198 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2200 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2201 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2202 throw INTERP_KERNEL::Exception(oss.str().c_str());
2204 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2205 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2207 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2208 throw INTERP_KERNEL::Exception(oss.str().c_str());
2210 int nbOfCells=getNumberOfCells();
2211 bool easyAssign=true;
2212 const int *connI=_nodal_connec_index->getConstPointer();
2213 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2215 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2217 if(it>=0 && it<nbOfCells)
2219 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2223 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2224 throw INTERP_KERNEL::Exception(oss.str().c_str());
2229 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2234 DataArrayInt *arrOut=0,*arrIOut=0;
2235 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2238 setConnectivity(arrOut,arrIOut,true);
2243 * Finds cells whose all nodes are in a given array of node ids.
2244 * \param [in] partBg - the array of node ids.
2245 * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2246 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2247 * cells. The caller is to delete this array using decrRef() as it is no
2249 * \throw If the coordinates array is not set.
2250 * \throw If the nodal connectivity of cells is not defined.
2251 * \throw If any cell id in \a partBg is not valid.
2253 * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2254 * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2256 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2258 DataArrayInt *cellIdsKept=0;
2259 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2260 cellIdsKept->setName(getName());
2265 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2266 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2267 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2268 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2270 * \param [in] begin input start of array of node ids.
2271 * \param [in] end input end of array of node ids.
2272 * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
2273 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2275 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2278 checkConnectivityFullyDefined();
2280 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2281 std::vector<bool> fastFinder(sz,false);
2282 for(const int *work=begin;work!=end;work++)
2283 if(*work>=0 && *work<sz)
2284 fastFinder[*work]=true;
2285 int nbOfCells=getNumberOfCells();
2286 const int *conn=getNodalConnectivity()->getConstPointer();
2287 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2288 for(int i=0;i<nbOfCells;i++)
2290 int ref=0,nbOfHit=0;
2291 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2295 if(fastFinder[*work2])
2298 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2299 cellIdsKept->pushBackSilent(i);
2301 cellIdsKeptArr=cellIdsKept.retn();
2305 * Finds cells whose all or some nodes are in a given array of node ids.
2306 * \param [in] begin - the array of node ids.
2307 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2308 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2309 * array \a begin are returned only, else cells whose any node is in the
2310 * array \a begin are returned.
2311 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2312 * cells. The caller is to delete this array using decrRef() as it is no more
2314 * \throw If the coordinates array is not set.
2315 * \throw If the nodal connectivity of cells is not defined.
2316 * \throw If any cell id in \a begin is not valid.
2318 * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2319 * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2321 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2323 DataArrayInt *cellIdsKept=0;
2324 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2325 cellIdsKept->setName(getName());
2330 Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
2331 copy are selected basing on specified node ids and the value of \a fullyIn
2332 parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the
2333 array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
2334 node is in the array of node ids. The created mesh shares the node coordinates array
2336 * \param [in] begin - the array of node ids.
2337 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2338 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2339 * array \a begin are copied, else cells whose any node is in the
2340 * array \a begin are copied.
2341 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2342 * to delete this mesh using decrRef() as it is no more needed.
2343 * \throw If the coordinates array is not set.
2344 * \throw If the nodal connectivity of cells is not defined.
2345 * \throw If any node id in \a begin is not valid.
2347 * \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
2348 * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
2350 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2352 DataArrayInt *cellIdsKept=0;
2353 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2355 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2359 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2360 * this->getMeshDimension(), that bound some cells of \a this mesh.
2361 * The cells of lower dimension to include to the result mesh are selected basing on
2362 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2363 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2364 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2365 * created mesh shares the node coordinates array with \a this mesh.
2366 * \param [in] begin - the array of node ids.
2367 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2368 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2369 * array \a begin are added, else cells whose any node is in the
2370 * array \a begin are added.
2371 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2372 * to delete this mesh using decrRef() as it is no more needed.
2373 * \throw If the coordinates array is not set.
2374 * \throw If the nodal connectivity of cells is not defined.
2375 * \throw If any node id in \a begin is not valid.
2377 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2378 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2380 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2382 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2383 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2384 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2385 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2386 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2390 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2391 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2392 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2393 * array of \a this mesh, else "free" nodes are removed from the result mesh
2394 * by calling zipCoords().
2395 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2396 * to delete this mesh using decrRef() as it is no more needed.
2397 * \throw If the coordinates array is not set.
2398 * \throw If the nodal connectivity of cells is not defined.
2400 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2401 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2403 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2405 DataArrayInt *desc=DataArrayInt::New();
2406 DataArrayInt *descIndx=DataArrayInt::New();
2407 DataArrayInt *revDesc=DataArrayInt::New();
2408 DataArrayInt *revDescIndx=DataArrayInt::New();
2410 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2413 descIndx->decrRef();
2414 int nbOfCells=meshDM1->getNumberOfCells();
2415 const int *revDescIndxC=revDescIndx->getConstPointer();
2416 std::vector<int> boundaryCells;
2417 for(int i=0;i<nbOfCells;i++)
2418 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2419 boundaryCells.push_back(i);
2420 revDescIndx->decrRef();
2421 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2426 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2427 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2428 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
2430 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2432 checkFullyDefined();
2433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2434 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2436 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2438 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2439 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2441 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2442 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2443 const int *revDescPtr=revDesc->getConstPointer();
2444 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2445 int nbOfCells=getNumberOfCells();
2446 std::vector<bool> ret1(nbOfCells,false);
2448 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2449 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2450 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2452 DataArrayInt *ret2=DataArrayInt::New();
2454 int *ret2Ptr=ret2->getPointer();
2456 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2459 ret2->setName("BoundaryCells");
2464 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2465 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2466 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2467 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2469 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2470 * This method method returns cells ids set s = s1 + s2 where :
2472 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2473 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2475 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2476 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2478 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2479 * \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
2480 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2482 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2484 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2485 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2486 checkConnectivityFullyDefined();
2487 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2488 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2489 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2491 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2492 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2493 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2494 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2495 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2496 DataArrayInt *idsOtherInConsti=0;
2497 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2498 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2500 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2502 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2503 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2504 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2506 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2507 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2509 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2510 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2511 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2512 neighThisPartAuto=0;
2513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2514 const int li[2]={0,1};
2515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2516 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2520 cellIdsRk0=s0arr.retn();
2521 cellIdsRk1=s_renum1.retn();
2525 * 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
2526 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2528 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2530 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2535 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2537 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2538 revDesc=0; desc=0; descIndx=0;
2539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2541 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2545 * Finds nodes lying on the boundary of \a this mesh.
2546 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2547 * nodes. The caller is to delete this array using decrRef() as it is no
2549 * \throw If the coordinates array is not set.
2550 * \throw If the nodal connectivity of cells is node defined.
2552 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2553 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2555 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2557 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2558 return skin->computeFetchedNodeIds();
2561 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2564 return const_cast<MEDCouplingUMesh *>(this);
2568 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2569 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
2570 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2571 * array is modified accordingly.
2572 * \param [in] newNodeNumbers - a permutation array, of length \a
2573 * this->getNumberOfNodes(), in "Old to New" mode.
2574 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2575 * \param [in] newNbOfNodes - number of nodes remaining after renumbering.
2576 * \throw If the coordinates array is not set.
2577 * \throw If the nodal connectivity of cells is not defined.
2579 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2580 * \ref py_mcumesh_renumberNodes "Here is a Python example".
2582 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2584 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2585 renumberNodesInConn(newNodeNumbers);
2589 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2590 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
2591 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2592 * array is modified accordingly. In contrast to renumberNodes(), location
2593 * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
2594 * \param [in] newNodeNumbers - a permutation array, of length \a
2595 * this->getNumberOfNodes(), in "Old to New" mode.
2596 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2597 * \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
2598 * actually one more than the maximal id in \a newNodeNumbers.
2599 * \throw If the coordinates array is not set.
2600 * \throw If the nodal connectivity of cells is not defined.
2602 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2603 * \ref py_mcumesh_renumberNodes "Here is a Python example".
2605 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2607 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2608 renumberNodesInConn(newNodeNumbers);
2612 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2613 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2614 * 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.
2615 * 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.
2616 * 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.
2618 * \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
2619 * parameter is altered during the call.
2620 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2621 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2622 * \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.
2624 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2626 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2627 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2629 checkFullyDefined();
2630 otherDimM1OnSameCoords.checkFullyDefined();
2631 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2632 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2633 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2634 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2635 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2636 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2639 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2640 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2642 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2644 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2646 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2648 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2649 DataArrayInt *idsTmp=0;
2650 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2653 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2654 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2655 DataArrayInt *tmp0=0,*tmp1=0;
2656 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2661 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2662 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2664 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2665 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2666 nodeIdsToDuplicate=s3.retn();
2670 * This method operates a modification of the connectivity and coords in \b this.
2671 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2672 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2673 * 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
2674 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2675 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2677 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2679 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2680 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2682 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2684 int nbOfNodes=getNumberOfNodes();
2685 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2686 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2690 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2691 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2692 * This method is a generalization of shiftNodeNumbersInConn().
2693 * \warning This method performs no check of validity of new ids. **Use it with care !**
2694 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2695 * this->getNumberOfNodes(), in "Old to New" mode.
2696 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2697 * \throw If the nodal connectivity of cells is not defined.
2699 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2700 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2702 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2704 checkConnectivityFullyDefined();
2705 int *conn=getNodalConnectivity()->getPointer();
2706 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2707 int nbOfCells=getNumberOfCells();
2708 for(int i=0;i<nbOfCells;i++)
2709 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2711 int& node=conn[iconn];
2712 if(node>=0)//avoid polyhedron separator
2714 node=newNodeNumbersO2N[node];
2717 _nodal_connec->declareAsNew();
2722 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2723 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2724 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2726 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2728 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2730 checkConnectivityFullyDefined();
2731 int *conn=getNodalConnectivity()->getPointer();
2732 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2733 int nbOfCells=getNumberOfCells();
2734 for(int i=0;i<nbOfCells;i++)
2735 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2737 int& node=conn[iconn];
2738 if(node>=0)//avoid polyhedron separator
2743 _nodal_connec->declareAsNew();
2748 * This method operates a modification of the connectivity in \b this.
2749 * 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.
2750 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2751 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2752 * 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
2753 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2754 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2756 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2757 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2759 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2760 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2761 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2763 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2765 checkConnectivityFullyDefined();
2766 std::map<int,int> m;
2768 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2770 int *conn=getNodalConnectivity()->getPointer();
2771 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2772 int nbOfCells=getNumberOfCells();
2773 for(int i=0;i<nbOfCells;i++)
2774 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2776 int& node=conn[iconn];
2777 if(node>=0)//avoid polyhedron separator
2779 std::map<int,int>::iterator it=m.find(node);
2788 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2790 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2791 * After the call of this method the number of cells remains the same as before.
2793 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2794 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2795 * be strictly in [0;this->getNumberOfCells()).
2797 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2798 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2799 * should be contained in[0;this->getNumberOfCells()).
2801 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2803 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2805 checkConnectivityFullyDefined();
2806 int nbCells=getNumberOfCells();
2807 const int *array=old2NewBg;
2809 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2811 const int *conn=_nodal_connec->getConstPointer();
2812 const int *connI=_nodal_connec_index->getConstPointer();
2813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2814 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2815 newConn->copyStringInfoFrom(*_nodal_connec);
2816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2817 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2818 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2820 int *newC=newConn->getPointer();
2821 int *newCI=newConnI->getPointer();
2824 for(int i=0;i<nbCells;i++)
2826 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2827 int nbOfElts=connI[pos+1]-connI[pos];
2828 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2833 setConnectivity(newConn,newConnI);
2835 delete [] const_cast<int *>(array);
2839 * Finds cells whose bounding boxes intersect a given bounding box.
2840 * \param [in] bbox - an array defining the bounding box via coordinates of its
2841 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2843 * \param [in] eps - a factor used to increase size of the bounding box of cell
2844 * before comparing it with \a bbox. This factor is multiplied by the maximal
2845 * extent of the bounding box of cell to produce an addition to this bounding box.
2846 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2847 * cells. The caller is to delete this array using decrRef() as it is no more
2849 * \throw If the coordinates array is not set.
2850 * \throw If the nodal connectivity of cells is not defined.
2852 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2853 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2855 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2858 if(getMeshDimension()==-1)
2860 elems->pushBackSilent(0);
2861 return elems.retn();
2863 int dim=getSpaceDimension();
2864 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2865 const int* conn = getNodalConnectivity()->getConstPointer();
2866 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2867 const double* coords = getCoords()->getConstPointer();
2868 int nbOfCells=getNumberOfCells();
2869 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2871 for (int i=0; i<dim; i++)
2873 elem_bb[i*2]=std::numeric_limits<double>::max();
2874 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2877 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2879 int node= conn[inode];
2880 if(node>=0)//avoid polyhedron separator
2882 for (int idim=0; idim<dim; idim++)
2884 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2886 elem_bb[idim*2] = coords[node*dim+idim] ;
2888 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2890 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2895 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2896 elems->pushBackSilent(ielem);
2898 return elems.retn();
2902 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2903 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2904 * added in 'elems' parameter.
2906 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2909 if(getMeshDimension()==-1)
2911 elems->pushBackSilent(0);
2912 return elems.retn();
2914 int dim=getSpaceDimension();
2915 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2916 const int* conn = getNodalConnectivity()->getConstPointer();
2917 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2918 const double* coords = getCoords()->getConstPointer();
2919 int nbOfCells=getNumberOfCells();
2920 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2922 for (int i=0; i<dim; i++)
2924 elem_bb[i*2]=std::numeric_limits<double>::max();
2925 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2928 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2930 int node= conn[inode];
2931 if(node>=0)//avoid polyhedron separator
2933 for (int idim=0; idim<dim; idim++)
2935 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2937 elem_bb[idim*2] = coords[node*dim+idim] ;
2939 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2941 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2946 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2947 elems->pushBackSilent(ielem);
2949 return elems.retn();
2953 * Returns a type of a cell by its id.
2954 * \param [in] cellId - the id of the cell of interest.
2955 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2956 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2958 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2960 const int *ptI=_nodal_connec_index->getConstPointer();
2961 const int *pt=_nodal_connec->getConstPointer();
2962 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2963 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2966 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2967 throw INTERP_KERNEL::Exception(oss.str().c_str());
2972 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2973 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2974 * The coordinates array is not considered here.
2976 * \param [in] type the geometric type
2977 * \return cell ids in this having geometric type \a type.
2979 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2984 checkConnectivityFullyDefined();
2985 int nbCells=getNumberOfCells();
2986 int mdim=getMeshDimension();
2987 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2988 if(mdim!=(int)cm.getDimension())
2989 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2990 const int *ptI=_nodal_connec_index->getConstPointer();
2991 const int *pt=_nodal_connec->getConstPointer();
2992 for(int i=0;i<nbCells;i++)
2994 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2995 ret->pushBackSilent(i);
3001 * Returns nb of cells having the geometric type 'type'.
3003 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3005 const int *ptI=_nodal_connec_index->getConstPointer();
3006 const int *pt=_nodal_connec->getConstPointer();
3007 int nbOfCells=getNumberOfCells();
3009 for(int i=0;i<nbOfCells;i++)
3010 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3016 * Returns the nodal connectivity of a given cell.
3017 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3018 * all returned node ids can be used in getCoordinatesOfNode().
3019 * \param [in] cellId - an id of the cell of interest.
3020 * \param [in,out] conn - a vector where the node ids are appended. It is not
3021 * cleared before the appending.
3022 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3024 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3026 const int *ptI=_nodal_connec_index->getConstPointer();
3027 const int *pt=_nodal_connec->getConstPointer();
3028 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3033 std::string MEDCouplingUMesh::simpleRepr() const
3035 static const char msg0[]="No coordinates specified !";
3036 std::ostringstream ret;
3037 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3038 ret << "Description of mesh : \"" << getDescription() << "\"\n";
3040 double tt=getTime(tmpp1,tmpp2);
3041 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3042 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
3044 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3046 { ret << " Mesh dimension has not been set or is invalid !"; }
3049 const int spaceDim=getSpaceDimension();
3050 ret << spaceDim << "\nInfo attached on space dimension : ";
3051 for(int i=0;i<spaceDim;i++)
3052 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3056 ret << msg0 << "\n";
3057 ret << "Number of nodes : ";
3059 ret << getNumberOfNodes() << "\n";
3061 ret << msg0 << "\n";
3062 ret << "Number of cells : ";
3063 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3064 ret << getNumberOfCells() << "\n";
3066 ret << "No connectivity specified !" << "\n";
3067 ret << "Cell types present : ";
3068 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3070 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3071 ret << cm.getRepr() << " ";
3077 std::string MEDCouplingUMesh::advancedRepr() const
3079 std::ostringstream ret;
3080 ret << simpleRepr();
3081 ret << "\nCoordinates array : \n___________________\n\n";
3083 _coords->reprWithoutNameStream(ret);
3085 ret << "No array set !\n";
3086 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3087 reprConnectivityOfThisLL(ret);
3092 * This method returns a C++ code that is a dump of \a this.
3093 * This method will throw if this is not fully defined.
3095 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
3097 static const char coordsName[]="coords";
3098 static const char connName[]="conn";
3099 static const char connIName[]="connI";
3100 checkFullyDefined();
3101 std::ostringstream ret; ret << "// coordinates" << std::endl;
3102 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3103 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3104 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3105 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3106 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3107 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3108 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3112 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3114 std::ostringstream ret;
3115 reprConnectivityOfThisLL(ret);
3120 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
3121 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3122 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3125 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3126 * This method analyzes the 3 arrays of 'this'. For each the following behaviour is done : if the array is null a newly one is created
3127 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3129 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
3131 int mdim=getMeshDimension();
3133 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3134 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3136 bool needToCpyCT=true;
3139 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3147 if(!_nodal_connec_index)
3149 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3154 tmp2=_nodal_connec_index;
3157 ret->setConnectivity(tmp1,tmp2,false);
3162 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3163 ret->setCoords(coords);
3166 ret->setCoords(_coords);
3170 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3172 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3174 int nbOfCells=getNumberOfCells();
3175 const int *c=_nodal_connec->getConstPointer();
3176 const int *ci=_nodal_connec_index->getConstPointer();
3177 for(int i=0;i<nbOfCells;i++)
3179 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3180 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3181 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3186 stream << "Connectivity not defined !\n";
3189 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3191 const int *ptI=_nodal_connec_index->getConstPointer();
3192 const int *pt=_nodal_connec->getConstPointer();
3193 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3194 return ptI[cellId+1]-ptI[cellId]-1;
3196 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3200 * Returns types of cells of the specified part of \a this mesh.
3201 * This method avoids computing sub-mesh explicitely to get its types.
3202 * \param [in] begin - an array of cell ids of interest.
3203 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3204 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3205 * describing the cell types.
3206 * \throw If the coordinates array is not set.
3207 * \throw If the nodal connectivity of cells is not defined.
3210 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
3212 checkFullyDefined();
3213 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3214 const int *conn=_nodal_connec->getConstPointer();
3215 const int *connIndex=_nodal_connec_index->getConstPointer();
3216 for(const int *w=begin;w!=end;w++)
3217 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3222 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3223 * a set of types of cells constituting \a this mesh.
3224 * This method is for advanced users having prepared their connectivity before. For
3225 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3226 * \param [in] conn - the nodal connectivity array.
3227 * \param [in] connIndex - the nodal connectivity index array.
3228 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3231 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3233 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3234 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3235 if(isComputingTypes)
3241 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
3242 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3244 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3245 _nodal_connec(0),_nodal_connec_index(0),
3246 _types(other._types)
3248 if(other._nodal_connec)
3249 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3250 if(other._nodal_connec_index)
3251 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3254 MEDCouplingUMesh::~MEDCouplingUMesh()
3257 _nodal_connec->decrRef();
3258 if(_nodal_connec_index)
3259 _nodal_connec_index->decrRef();
3263 * Recomputes a set of cell types of \a this mesh. For more info see
3264 * \ref MEDCouplingUMeshNodalConnectivity.
3266 void MEDCouplingUMesh::computeTypes()
3268 if(_nodal_connec && _nodal_connec_index)
3271 const int *conn=_nodal_connec->getConstPointer();
3272 const int *connIndex=_nodal_connec_index->getConstPointer();
3273 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3275 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3276 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3281 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3283 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3285 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3286 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3290 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3292 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3294 if(!_nodal_connec_index || !_nodal_connec)
3295 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3299 * Returns a number of cells constituting \a this mesh.
3300 * \return int - the number of cells in \a this mesh.
3301 * \throw If the nodal connectivity of cells is not defined.
3303 int MEDCouplingUMesh::getNumberOfCells() const
3305 if(_nodal_connec_index)
3306 return _nodal_connec_index->getNumberOfTuples()-1;
3311 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3315 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3316 * mesh. For more info see \ref MEDCouplingMeshesPage.
3317 * \return int - the dimension of \a this mesh.
3318 * \throw If the mesh dimension is not defined using setMeshDimension().
3320 int MEDCouplingUMesh::getMeshDimension() const
3323 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3328 * Returns a length of the nodal connectivity array.
3329 * This method is for test reason. Normally the integer returned is not useable by
3330 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3331 * \return int - the length of the nodal connectivity array.
3333 int MEDCouplingUMesh::getMeshLength() const
3335 return _nodal_connec->getNbOfElems();
3339 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3341 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3343 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3344 tinyInfo.push_back(getMeshDimension());
3345 tinyInfo.push_back(getNumberOfCells());
3347 tinyInfo.push_back(getMeshLength());
3349 tinyInfo.push_back(-1);
3353 * First step of unserialization process.
3355 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3357 return tinyInfo[6]<=0;
3361 * Second step of serialization process.
3362 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3364 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3366 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3368 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3372 * Third and final step of serialization process.
3374 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3376 MEDCouplingPointSet::serialize(a1,a2);
3377 if(getMeshDimension()>-1)
3379 a1=DataArrayInt::New();
3380 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3381 int *ptA1=a1->getPointer();
3382 const int *conn=getNodalConnectivity()->getConstPointer();
3383 const int *index=getNodalConnectivityIndex()->getConstPointer();
3384 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3385 std::copy(conn,conn+getMeshLength(),ptA1);
3392 * Second and final unserialization process.
3393 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3395 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3397 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3398 setMeshDimension(tinyInfo[5]);
3402 const int *recvBuffer=a1->getConstPointer();
3403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3404 myConnecIndex->alloc(tinyInfo[6]+1,1);
3405 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3407 myConnec->alloc(tinyInfo[7],1);
3408 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3409 setConnectivity(myConnec, myConnecIndex);
3414 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3415 * CellIds are given using range specified by a start an end and step.
3417 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3419 checkFullyDefined();
3420 int ncell=getNumberOfCells();
3421 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3422 ret->_mesh_dim=_mesh_dim;
3423 ret->setCoords(_coords);
3424 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3426 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3428 const int *conn=_nodal_connec->getConstPointer();
3429 const int *connIndex=_nodal_connec_index->getConstPointer();
3430 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3432 if(work>=0 && work<ncell)
3434 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3438 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3439 throw INTERP_KERNEL::Exception(oss.str().c_str());
3442 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3443 int *newConnPtr=newConn->getPointer();
3444 std::set<INTERP_KERNEL::NormalizedCellType> types;
3446 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3448 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3449 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3451 ret->setConnectivity(newConn,newConnI,false);
3453 ret->copyTinyInfoFrom(this);
3458 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3459 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3460 * The return newly allocated mesh will share the same coordinates as 'this'.
3462 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3464 checkFullyDefined();
3465 int ncell=getNumberOfCells();
3466 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3467 ret->_mesh_dim=_mesh_dim;
3468 ret->setCoords(_coords);
3469 std::size_t nbOfElemsRet=std::distance(begin,end);
3470 int *connIndexRet=new int[nbOfElemsRet+1];
3472 const int *conn=_nodal_connec->getConstPointer();
3473 const int *connIndex=_nodal_connec_index->getConstPointer();
3475 for(const int *work=begin;work!=end;work++,newNbring++)
3477 if(*work>=0 && *work<ncell)
3478 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3481 delete [] connIndexRet;
3482 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3483 throw INTERP_KERNEL::Exception(oss.str().c_str());
3486 int *connRet=new int[connIndexRet[nbOfElemsRet]];
3487 int *connRetWork=connRet;
3488 std::set<INTERP_KERNEL::NormalizedCellType> types;
3489 for(const int *work=begin;work!=end;work++)
3491 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3492 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3494 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3495 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3496 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3497 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3498 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3500 ret->copyTinyInfoFrom(this);
3505 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3507 * For 1D cells, the returned field contains lengths.<br>
3508 * For 2D cells, the returned field contains areas.<br>
3509 * For 3D cells, the returned field contains volumes.
3510 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3511 * orientation, i.e. the volume is always positive.
3512 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3513 * and one time . The caller is to delete this field using decrRef() as it is no
3516 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3518 std::string name="MeasureOfMesh_";
3520 int nbelem=getNumberOfCells();
3521 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3522 field->setName(name.c_str());
3523 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3524 array->alloc(nbelem,1);
3525 double *area_vol=array->getPointer();
3526 field->setArray(array) ; array=0;
3527 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3528 field->synchronizeTimeWithMesh();
3529 if(getMeshDimension()!=-1)
3532 INTERP_KERNEL::NormalizedCellType type;
3533 int dim_space=getSpaceDimension();
3534 const double *coords=getCoords()->getConstPointer();
3535 const int *connec=getNodalConnectivity()->getConstPointer();
3536 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3537 for(int iel=0;iel<nbelem;iel++)
3539 ipt=connec_index[iel];
3540 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3541 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);
3544 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3548 area_vol[0]=std::numeric_limits<double>::max();
3550 return field.retn();
3554 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3556 * For 1D cells, the returned array contains lengths.<br>
3557 * For 2D cells, the returned array contains areas.<br>
3558 * For 3D cells, the returned array contains volumes.
3559 * This method avoids building explicitly a part of \a this mesh to perform the work.
3560 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3561 * orientation, i.e. the volume is always positive.
3562 * \param [in] begin - an array of cell ids of interest.
3563 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3564 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3565 * delete this array using decrRef() as it is no more needed.
3567 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3568 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3569 * \sa getMeasureField()
3571 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3573 std::string name="PartMeasureOfMesh_";
3575 int nbelem=(int)std::distance(begin,end);
3576 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3577 array->setName(name.c_str());
3578 array->alloc(nbelem,1);
3579 double *area_vol=array->getPointer();
3580 if(getMeshDimension()!=-1)
3583 INTERP_KERNEL::NormalizedCellType type;
3584 int dim_space=getSpaceDimension();
3585 const double *coords=getCoords()->getConstPointer();
3586 const int *connec=getNodalConnectivity()->getConstPointer();
3587 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3588 for(const int *iel=begin;iel!=end;iel++)
3590 ipt=connec_index[*iel];
3591 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3592 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3595 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3599 area_vol[0]=std::numeric_limits<double>::max();
3601 return array.retn();
3605 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3606 * \a this one. The returned field contains the dual cell volume for each corresponding
3607 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3608 * the dual mesh in P1 sens of \a this.<br>
3609 * For 1D cells, the returned field contains lengths.<br>
3610 * For 2D cells, the returned field contains areas.<br>
3611 * For 3D cells, the returned field contains volumes.
3612 * This method is useful to check "P1*" conservative interpolators.
3613 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3614 * orientation, i.e. the volume is always positive.
3615 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3616 * nodes and one time. The caller is to delete this array using decrRef() as
3617 * it is no more needed.
3619 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3621 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3622 std::string name="MeasureOnNodeOfMesh_";
3624 int nbNodes=getNumberOfNodes();
3625 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3626 double cst=1./((double)getMeshDimension()+1.);
3627 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3628 array->alloc(nbNodes,1);
3629 double *valsToFill=array->getPointer();
3630 std::fill(valsToFill,valsToFill+nbNodes,0.);
3631 const double *values=tmp->getArray()->getConstPointer();
3632 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3633 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3634 getReverseNodalConnectivity(da,daInd);
3635 const int *daPtr=da->getConstPointer();
3636 const int *daIPtr=daInd->getConstPointer();
3637 for(int i=0;i<nbNodes;i++)
3638 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3639 valsToFill[i]+=cst*values[*cell];
3641 ret->setArray(array);
3646 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3647 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3648 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3649 * and are normalized.
3650 * <br> \a this can be either
3651 * - a 2D mesh in 2D or 3D space or
3652 * - an 1D mesh in 2D space.
3654 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3655 * cells and one time. The caller is to delete this field using decrRef() as
3656 * it is no more needed.
3657 * \throw If the nodal connectivity of cells is not defined.
3658 * \throw If the coordinates array is not set.
3659 * \throw If the mesh dimension is not set.
3660 * \throw If the mesh and space dimension is not as specified above.
3662 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3664 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3665 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3666 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3667 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3668 int nbOfCells=getNumberOfCells();
3669 int nbComp=getMeshDimension()+1;
3670 array->alloc(nbOfCells,nbComp);
3671 double *vals=array->getPointer();
3672 const int *connI=_nodal_connec_index->getConstPointer();
3673 const int *conn=_nodal_connec->getConstPointer();
3674 const double *coords=_coords->getConstPointer();
3675 if(getMeshDimension()==2)
3677 if(getSpaceDimension()==3)
3679 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3680 const double *locPtr=loc->getConstPointer();
3681 for(int i=0;i<nbOfCells;i++,vals+=3)
3683 int offset=connI[i];
3684 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3685 double n=INTERP_KERNEL::norm<3>(vals);
3686 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3691 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3692 const double *isAbsPtr=isAbs->getArray()->begin();
3693 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3694 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3697 else//meshdimension==1
3700 for(int i=0;i<nbOfCells;i++)
3702 int offset=connI[i];
3703 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3704 double n=INTERP_KERNEL::norm<2>(tmp);
3705 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3710 ret->setArray(array);
3712 ret->synchronizeTimeWithSupport();
3717 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3718 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3719 * and are normalized.
3720 * <br> \a this can be either
3721 * - a 2D mesh in 2D or 3D space or
3722 * - an 1D mesh in 2D space.
3724 * This method avoids building explicitly a part of \a this mesh to perform the work.
3725 * \param [in] begin - an array of cell ids of interest.
3726 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3727 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3728 * cells and one time. The caller is to delete this field using decrRef() as
3729 * it is no more needed.
3730 * \throw If the nodal connectivity of cells is not defined.
3731 * \throw If the coordinates array is not set.
3732 * \throw If the mesh dimension is not set.
3733 * \throw If the mesh and space dimension is not as specified above.
3734 * \sa buildOrthogonalField()
3736 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3737 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3739 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3741 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3742 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3743 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3744 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3745 std::size_t nbelems=std::distance(begin,end);
3746 int nbComp=getMeshDimension()+1;
3747 array->alloc((int)nbelems,nbComp);
3748 double *vals=array->getPointer();
3749 const int *connI=_nodal_connec_index->getConstPointer();
3750 const int *conn=_nodal_connec->getConstPointer();
3751 const double *coords=_coords->getConstPointer();
3752 if(getMeshDimension()==2)
3754 if(getSpaceDimension()==3)
3756 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3757 const double *locPtr=loc->getConstPointer();
3758 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3760 int offset=connI[*i];
3761 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3762 double n=INTERP_KERNEL::norm<3>(vals);
3763 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3768 for(std::size_t i=0;i<nbelems;i++)
3769 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3772 else//meshdimension==1
3775 for(const int *i=begin;i!=end;i++)
3777 int offset=connI[*i];
3778 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3779 double n=INTERP_KERNEL::norm<2>(tmp);
3780 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3785 ret->setArray(array);
3787 ret->synchronizeTimeWithSupport();
3792 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3793 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3794 * and are \b not normalized.
3795 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3796 * cells and one time. The caller is to delete this field using decrRef() as
3797 * it is no more needed.
3798 * \throw If the nodal connectivity of cells is not defined.
3799 * \throw If the coordinates array is not set.
3800 * \throw If \a this->getMeshDimension() != 1.
3801 * \throw If \a this mesh includes cells of type other than SEG2.
3803 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3805 if(getMeshDimension()!=1)
3806 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3807 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3808 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3809 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3810 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3811 int nbOfCells=getNumberOfCells();
3812 int spaceDim=getSpaceDimension();
3813 array->alloc(nbOfCells,spaceDim);
3814 double *pt=array->getPointer();
3815 const double *coo=getCoords()->getConstPointer();
3816 std::vector<int> conn;
3818 for(int i=0;i<nbOfCells;i++)
3821 getNodeIdsOfCell(i,conn);
3822 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3824 ret->setArray(array);
3826 ret->synchronizeTimeWithSupport();
3831 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3832 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3833 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3834 * from. If a result face is shared by two 3D cells, then the face in included twice in
3836 * \param [in] origin - 3 components of a point defining location of the plane.
3837 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3838 * must be greater than 1e-6.
3839 * \param [in] eps - half-thickness of the plane.
3840 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3841 * producing correspondent 2D cells. The caller is to delete this array
3842 * using decrRef() as it is no more needed.
3843 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3844 * not share the node coordinates array with \a this mesh. The caller is to
3845 * delete this mesh using decrRef() as it is no more needed.
3846 * \throw If the coordinates array is not set.
3847 * \throw If the nodal connectivity of cells is not defined.
3848 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3849 * \throw If magnitude of \a vec is less than 1e-6.
3850 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3851 * \throw If \a this includes quadratic cells.
3853 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3855 checkFullyDefined();
3856 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3858 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3859 if(candidates->empty())
3860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3861 std::vector<int> nodes;
3862 DataArrayInt *cellIds1D=0;
3863 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3864 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3867 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3869 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3870 revDesc2=0; revDescIndx2=0;
3871 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3872 revDesc1=0; revDescIndx1=0;
3873 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3874 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3876 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3877 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3879 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3880 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3881 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3882 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3883 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3885 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3886 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3887 if(cellIds2->empty())
3888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3889 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3890 ret->setCoords(mDesc1->getCoords());
3891 ret->setConnectivity(conn,connI,true);
3892 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3897 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3898 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
3899 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3901 * \param [in] origin - 3 components of a point defining location of the plane.
3902 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3903 * must be greater than 1e-6.
3904 * \param [in] eps - half-thickness of the plane.
3905 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3906 * producing correspondent segments. The caller is to delete this array
3907 * using decrRef() as it is no more needed.
3908 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3909 * mesh in 3D space. This mesh does not share the node coordinates array with
3910 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3912 * \throw If the coordinates array is not set.
3913 * \throw If the nodal connectivity of cells is not defined.
3914 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3915 * \throw If magnitude of \a vec is less than 1e-6.
3916 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3917 * \throw If \a this includes quadratic cells.
3919 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3921 checkFullyDefined();
3922 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3925 if(candidates->empty())
3926 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3927 std::vector<int> nodes;
3928 DataArrayInt *cellIds1D=0;
3929 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3930 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3931 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3935 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3936 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3937 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3939 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3940 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3942 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3943 int ncellsSub=subMesh->getNumberOfCells();
3944 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3945 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3946 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3947 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3950 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3951 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3952 for(int i=0;i<ncellsSub;i++)
3954 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3956 if(cut3DSurf[i].first!=-2)
3958 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3959 connI->pushBackSilent(conn->getNumberOfTuples());
3960 cellIds2->pushBackSilent(i);
3964 int cellId3DSurf=cut3DSurf[i].second;
3965 int offset=nodalI[cellId3DSurf]+1;
3966 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3967 for(int j=0;j<nbOfEdges;j++)
3969 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3970 connI->pushBackSilent(conn->getNumberOfTuples());
3971 cellIds2->pushBackSilent(cellId3DSurf);
3976 if(cellIds2->empty())
3977 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3978 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3979 ret->setCoords(mDesc1->getCoords());
3980 ret->setConnectivity(conn,connI,true);
3981 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3986 * Finds cells whose bounding boxes intersect a given plane.
3987 * \param [in] origin - 3 components of a point defining location of the plane.
3988 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3989 * must be greater than 1e-6.
3990 * \param [in] eps - half-thickness of the plane.
3991 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3992 * cells. The caller is to delete this array using decrRef() as it is no more
3994 * \throw If the coordinates array is not set.
3995 * \throw If the nodal connectivity of cells is not defined.
3996 * \throw If \a this->getSpaceDimension() != 3.
3997 * \throw If magnitude of \a vec is less than 1e-6.
3998 * \sa buildSlice3D()
4000 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
4002 checkFullyDefined();
4003 if(getSpaceDimension()!=3)
4004 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4005 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4007 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4009 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4010 double angle=acos(vec[2]/normm);
4011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
4015 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
4016 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4017 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4019 mw->getBoundingBox(bbox);
4020 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4021 cellIds=mw->getCellsInBoundingBox(bbox,eps);
4025 getBoundingBox(bbox);
4026 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4027 cellIds=getCellsInBoundingBox(bbox,eps);
4029 return cellIds.retn();
4033 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4034 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4035 * No consideration of coordinate is done by this method.
4036 * 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)
4037 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
4039 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
4041 if(getMeshDimension()!=1)
4042 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4043 int nbCells=getNumberOfCells();
4045 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4046 const int *connI=_nodal_connec_index->getConstPointer();
4047 const int *conn=_nodal_connec->getConstPointer();
4048 int ref=conn[connI[0]+2];
4049 for(int i=1;i<nbCells;i++)
4051 if(conn[connI[i]+1]!=ref)
4053 ref=conn[connI[i]+2];
4059 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4060 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4061 * @param pt reference point of the line
4062 * @param v normalized director vector of the line
4063 * @param eps max precision before throwing an exception
4064 * @param res output of size this->getNumberOfCells
4066 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4068 if(getMeshDimension()!=1)
4069 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4070 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4071 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4072 if(getSpaceDimension()!=3)
4073 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4074 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4075 const double *fPtr=f->getArray()->getConstPointer();
4077 for(int i=0;i<getNumberOfCells();i++)
4079 const double *tmp1=fPtr+3*i;
4080 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4081 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4082 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4083 double n1=INTERP_KERNEL::norm<3>(tmp);
4084 n1/=INTERP_KERNEL::norm<3>(tmp1);
4086 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4088 const double *coo=getCoords()->getConstPointer();
4089 for(int i=0;i<getNumberOfNodes();i++)
4091 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4092 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4093 res[i]=std::accumulate(tmp,tmp+3,0.);
4098 * This method computes the distance from a point \a pt to \a this and the first \a cellId and \a nodeId in \a this corresponding to the returned distance.
4099 * \a this is expected to be a mesh so that its space dimension is equal to its
4100 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4101 * 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).
4103 * This method firstly find the closer node in \a this to the requested point whose coordinates are defined by [ \a ptBg, \a ptEnd ). Then for this node found
4104 * the cells sharing this node (if any) are considered to find if the distance to these cell are smaller than the result found previously. If no cells are linked
4105 * to the node that minimizes distance with the input point then -1 is returned in cellId.
4107 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4108 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4110 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4111 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4112 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4113 * \return the positive value of the distance.
4114 * \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
4116 * \sa DataArrayDouble::distanceToTuple
4118 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
4120 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4121 if(meshDim!=spaceDim-1)
4122 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4123 if(meshDim!=2 && meshDim!=1)
4124 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4125 checkFullyDefined();
4126 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4127 { 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()); }
4129 double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
4131 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
4132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
4137 distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
4142 distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
4146 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4154 * \param [in] pt the start pointer (included) of the coordinates of the point
4155 * \param [in] cellIds
4156 * \param [in,out] ret0 the min distance between \a this and the external input point
4157 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4158 * \sa MEDCouplingUMesh::distanceToPoint
4160 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
4162 const double *coords=_coords->getConstPointer();
4164 if(cellIds->empty())
4166 const int *ptr=_nodal_connec->getConstPointer();
4167 const int *ptrI=_nodal_connec_index->getConstPointer();
4168 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
4170 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
4172 case INTERP_KERNEL::NORM_TRI3:
4174 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
4176 { ret0=tmp; cellId=*zeCell; }
4179 case INTERP_KERNEL::NORM_QUAD4:
4180 case INTERP_KERNEL::NORM_POLYGON:
4182 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
4184 { ret0=tmp; cellId=*zeCell; }
4188 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4194 * \param [in] pt the start pointer (included) of the coordinates of the point
4195 * \param [in] cellIds
4196 * \param [in,out] ret0 the min distance between \a this and the external input point
4197 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4198 * \sa MEDCouplingUMesh::distanceToPoint
4200 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
4202 const double *coords=_coords->getConstPointer();
4203 if(cellIds->empty())
4204 { cellId=-1; return; }
4205 const int *ptr=_nodal_connec->getConstPointer();
4206 const int *ptrI=_nodal_connec_index->getConstPointer();
4207 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
4209 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
4211 case INTERP_KERNEL::NORM_SEG2:
4213 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
4214 if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
4216 { ret0=tmp; cellId=*zeCell; }
4220 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4226 * Finds cells in contact with a ball (i.e. a point with precision).
4227 * \warning This method is suitable if the caller intends to evaluate only one
4228 * point, for more points getCellsContainingPoints() is recommended as it is
4230 * \param [in] pos - array of coordinates of the ball central point.
4231 * \param [in] eps - ball radius.
4232 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4233 * if there are no such cells.
4234 * \throw If the coordinates array is not set.
4235 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4237 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4239 std::vector<int> elts;
4240 getCellsContainingPoint(pos,eps,elts);
4243 return elts.front();
4247 * Finds cells in contact with a ball (i.e. a point with precision).
4248 * \warning This method is suitable if the caller intends to evaluate only one
4249 * point, for more points getCellsContainingPoints() is recommended as it is
4251 * \param [in] pos - array of coordinates of the ball central point.
4252 * \param [in] eps - ball radius.
4253 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
4254 * before inserting ids.
4255 * \throw If the coordinates array is not set.
4256 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4258 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4259 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4261 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4263 std::vector<int> eltsIndex;
4264 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4269 namespace ParaMEDMEM
4271 template<const int SPACEDIMM>
4275 static const int MY_SPACEDIM=SPACEDIMM;
4276 static const int MY_MESHDIM=8;
4277 typedef int MyConnType;
4278 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4280 // useless, but for windows compilation ...
4281 const double* getCoordinatesPtr() const { return 0; }
4282 const int* getConnectivityPtr() const { return 0; }
4283 const int* getConnectivityIndexPtr() const { return 0; }
4284 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4288 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4290 INTERP_KERNEL::Edge *ret=0;
4293 case INTERP_KERNEL::NORM_SEG2:
4295 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4298 case INTERP_KERNEL::NORM_SEG3:
4300 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4301 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4302 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4303 bool colinearity=inters.areColinears();
4304 delete e1; delete e2;
4306 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4308 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4309 mapp2[bg[2]].second=false;
4313 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4319 * 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'.
4320 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4321 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4323 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4326 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.
4327 const double *coo=mDesc->getCoords()->getConstPointer();
4328 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4329 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4331 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4332 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4333 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4335 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4336 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4338 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4339 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4341 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4342 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4344 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4346 if((*it2).second.second)
4347 mapp[(*it2).second.first]=(*it2).first;
4348 ((*it2).second.first)->decrRef();
4353 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4357 int locId=nodeId-offset2;
4358 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4362 int locId=nodeId-offset1;
4363 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4365 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4368 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4369 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4370 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4372 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4374 int eltId1=abs(*desc1)-1;
4375 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4377 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4378 if(it==mappRev.end())
4380 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4391 template<int SPACEDIM>
4392 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4393 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4395 std::vector<double> bbox;
4396 eltsIndex.resize(nbOfPoints+1);
4399 getBoundingBoxForBBTree(bbox);
4400 int nbOfCells=getNumberOfCells();
4401 const int *conn=_nodal_connec->getConstPointer();
4402 const int *connI=_nodal_connec_index->getConstPointer();
4403 double bb[2*SPACEDIM];
4404 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4405 for(int i=0;i<nbOfPoints;i++)
4407 eltsIndex[i+1]=eltsIndex[i];
4408 for(int j=0;j<SPACEDIM;j++)
4410 bb[2*j]=pos[SPACEDIM*i+j];
4411 bb[2*j+1]=pos[SPACEDIM*i+j];
4413 std::vector<int> candidates;
4414 myTree.getIntersectingElems(bb,candidates);
4415 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4417 int sz=connI[(*iter)+1]-connI[*iter]-1;
4418 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4419 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4420 coords,conn+connI[*iter]+1,sz,eps))
4423 elts.push_back(*iter);
4429 * Finds cells in contact with several balls (i.e. points with precision).
4430 * This method is an extension of getCellContainingPoint() and
4431 * getCellsContainingPoint() for the case of multiple points.
4432 * \param [in] pos - an array of coordinates of points in full interlace mode :
4433 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4434 * this->getSpaceDimension() * \a nbOfPoints
4435 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4436 * \param [in] eps - radius of balls (i.e. the precision).
4437 * \param [in,out] elts - vector returning ids of found cells.
4438 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4439 * dividing cell ids in \a elts into groups each referring to one
4440 * point. Its every element (except the last one) is an index pointing to the
4441 * first id of a group of cells. For example cells in contact with the *i*-th
4442 * point are described by following range of indices:
4443 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4444 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4445 * Number of cells in contact with the *i*-th point is
4446 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4447 * \throw If the coordinates array is not set.
4448 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4450 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4451 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4453 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4454 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4456 int spaceDim=getSpaceDimension();
4457 int mDim=getMeshDimension();
4462 const double *coords=_coords->getConstPointer();
4463 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4470 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4472 else if(spaceDim==2)
4476 const double *coords=_coords->getConstPointer();
4477 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4480 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4482 else if(spaceDim==1)
4486 const double *coords=_coords->getConstPointer();
4487 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4490 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4493 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4497 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4498 * least two its edges intersect each other anywhere except their extremities. An
4499 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4500 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4501 * cleared before filling in.
4502 * \param [in] eps - precision.
4503 * \throw If \a this->getMeshDimension() != 2.
4504 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4506 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4508 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4509 if(getMeshDimension()!=2)
4510 throw INTERP_KERNEL::Exception(msg);
4511 int spaceDim=getSpaceDimension();
4512 if(spaceDim!=2 && spaceDim!=3)
4513 throw INTERP_KERNEL::Exception(msg);
4514 const int *conn=_nodal_connec->getConstPointer();
4515 const int *connI=_nodal_connec_index->getConstPointer();
4516 int nbOfCells=getNumberOfCells();
4517 std::vector<double> cell2DinS2;
4518 for(int i=0;i<nbOfCells;i++)
4520 int offset=connI[i];
4521 int nbOfNodesForCell=connI[i+1]-offset-1;
4522 if(nbOfNodesForCell<=3)
4524 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4525 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4526 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4533 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4535 * 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.
4536 * 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.
4538 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4539 * This convex envelop is computed using Jarvis march algorithm.
4540 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4541 * 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)
4542 * 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.
4544 * @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.
4546 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4548 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4549 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4550 checkFullyDefined();
4551 const double *coords=getCoords()->getConstPointer();
4552 int nbOfCells=getNumberOfCells();
4553 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4554 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4555 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4556 int *workIndexOut=nodalConnecIndexOut->getPointer();
4558 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4559 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4560 std::set<INTERP_KERNEL::NormalizedCellType> types;
4561 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4562 isChanged->alloc(0,1);
4563 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4565 int pos=nodalConnecOut->getNumberOfTuples();
4566 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4567 isChanged->pushBackSilent(i);
4568 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4569 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4571 if(isChanged->empty())
4573 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4575 return isChanged.retn();
4579 * This method is \b NOT const because it can modify 'this'.
4580 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4581 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4582 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4583 * \b 1 for translation and rotation around point of 'mesh1D'.
4584 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
4586 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4588 checkFullyDefined();
4589 mesh1D->checkFullyDefined();
4590 if(!mesh1D->isContiguous1D())
4591 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4592 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4593 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4594 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4595 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4596 if(mesh1D->getMeshDimension()!=1)
4597 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4599 if(isPresenceOfQuadratic())
4601 if(mesh1D->isFullyQuadratic())
4604 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4607 int oldNbOfNodes=getNumberOfNodes();
4608 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4613 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4618 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4622 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4624 setCoords(newCoords);
4625 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4631 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4632 * If it is not the case an exception will be thrown.
4633 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4634 * intersection of plane defined by ('origin','vec').
4635 * This method has one in/out parameter : 'cut3DCurve'.
4636 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4637 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4638 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4639 * This method will throw an exception if 'this' contains a non linear segment.
4641 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4643 checkFullyDefined();
4644 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4645 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4646 int ncells=getNumberOfCells();
4647 int nnodes=getNumberOfNodes();
4648 double vec2[3],vec3[3],vec4[3];
4649 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4652 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4653 const int *conn=_nodal_connec->getConstPointer();
4654 const int *connI=_nodal_connec_index->getConstPointer();
4655 const double *coo=_coords->getConstPointer();
4656 std::vector<double> addCoo;
4657 for(int i=0;i<ncells;i++)
4659 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4661 if(cut3DCurve[i]==-2)
4663 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4664 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];
4665 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4666 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4667 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4669 const double *st2=coo+3*st;
4670 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4671 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]));
4672 if(pos>eps && pos<1-eps)
4674 int nNode=((int)addCoo.size())/3;
4675 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4676 addCoo.insert(addCoo.end(),vec4,vec4+3);
4677 cut3DCurve[i]=nnodes+nNode;
4683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4687 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4688 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4689 coo2->alloc(newNbOfNodes,3);
4690 double *tmp=coo2->getPointer();
4691 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4692 std::copy(addCoo.begin(),addCoo.end(),tmp);
4693 DataArrayDouble::SetArrayIn(coo2,_coords);
4698 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4699 * @param mesh1D is the input 1D mesh used for translation computation.
4700 * @return newCoords new coords filled by this method.
4702 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4704 int oldNbOfNodes=getNumberOfNodes();
4705 int nbOf1DCells=mesh1D->getNumberOfCells();
4706 int spaceDim=getSpaceDimension();
4707 DataArrayDouble *ret=DataArrayDouble::New();
4708 std::vector<bool> isQuads;
4709 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4710 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4711 double *retPtr=ret->getPointer();
4712 const double *coords=getCoords()->getConstPointer();
4713 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4715 std::vector<double> c;
4719 for(int i=0;i<nbOf1DCells;i++)
4722 mesh1D->getNodeIdsOfCell(i,v);
4724 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4725 mesh1D->getCoordinatesOfNode(v[0],c);
4726 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4727 for(int j=0;j<oldNbOfNodes;j++)
4728 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4732 mesh1D->getCoordinatesOfNode(v[1],c);
4733 mesh1D->getCoordinatesOfNode(v[0],c);
4734 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4735 for(int j=0;j<oldNbOfNodes;j++)
4736 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4739 ret->copyStringInfoFrom(*getCoords());
4744 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4745 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4746 * @return newCoords new coords filled by this method.
4748 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4750 if(mesh1D->getSpaceDimension()==2)
4751 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4752 if(mesh1D->getSpaceDimension()==3)
4753 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4754 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4758 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4759 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4760 * @return newCoords new coords filled by this method.
4762 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4765 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4766 int oldNbOfNodes=getNumberOfNodes();
4767 int nbOf1DCells=mesh1D->getNumberOfCells();
4769 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4770 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4771 int nbOfLevsInVec=nbOf1DCells+1;
4772 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4773 double *retPtr=ret->getPointer();
4774 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4775 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4776 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4777 tmp->setCoords(tmp2);
4778 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4779 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4780 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4781 for(int i=1;i<nbOfLevsInVec;i++)
4783 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4784 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4785 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4786 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4787 tmp->translate(vec);
4788 double tmp3[2],radius,alpha,alpha0;
4789 const double *p0=i+1<nbOfLevsInVec?begin:third;
4790 const double *p1=i+1<nbOfLevsInVec?end:begin;
4791 const double *p2=i+1<nbOfLevsInVec?third:end;
4792 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4793 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]);
4794 double angle=acos(cosangle/(radius*radius));
4795 tmp->rotate(end,0,angle);
4796 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4802 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4803 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4804 * @return newCoords new coords filled by this method.
4806 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4810 int oldNbOfNodes=getNumberOfNodes();
4811 int nbOf1DCells=mesh1D->getNumberOfCells();
4813 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4814 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4815 int nbOfLevsInVec=nbOf1DCells+1;
4816 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4817 double *retPtr=ret->getPointer();
4818 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4819 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4820 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4821 tmp->setCoords(tmp2);
4822 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4823 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4824 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4825 for(int i=1;i<nbOfLevsInVec;i++)
4827 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4828 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4829 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4830 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4831 tmp->translate(vec);
4832 double tmp3[2],radius,alpha,alpha0;
4833 const double *p0=i+1<nbOfLevsInVec?begin:third;
4834 const double *p1=i+1<nbOfLevsInVec?end:begin;
4835 const double *p2=i+1<nbOfLevsInVec?third:end;
4836 double vecPlane[3]={
4837 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4838 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4839 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4841 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4844 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4845 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4846 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4848 double c2=cos(asin(s2));
4850 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4851 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4852 {-vec2[1]*s2, vec2[0]*s2, c2}
4854 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]};
4855 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]};
4856 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]};
4857 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4858 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]);
4859 double angle=acos(cosangle/(radius*radius));
4860 tmp->rotate(end,vecPlane,angle);
4863 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4869 * This method is private because not easy to use for end user. This method is const contrary to
4870 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4871 * the coords sorted slice by slice.
4872 * @param isQuad specifies presence of quadratic cells.
4874 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4876 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4877 int nbOf2DCells=getNumberOfCells();
4878 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4879 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4880 const int *conn=_nodal_connec->getConstPointer();
4881 const int *connI=_nodal_connec_index->getConstPointer();
4882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4884 newConnI->alloc(nbOf3DCells+1,1);
4885 int *newConnIPtr=newConnI->getPointer();
4887 std::vector<int> newc;
4888 for(int j=0;j<nbOf2DCells;j++)
4890 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4891 *newConnIPtr++=(int)newc.size();
4893 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4894 int *newConnPtr=newConn->getPointer();
4895 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4896 newConnIPtr=newConnI->getPointer();
4897 for(int iz=0;iz<nbOf1DCells;iz++)
4900 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4901 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4903 int icell=(int)(iter-newc.begin());
4904 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4907 *newConnPtr=(*iter)+iz*deltaPerLev;
4912 *newConnPtr=(*iter);
4915 ret->setConnectivity(newConn,newConnI,true);
4916 ret->setCoords(getCoords());
4921 * Checks if \a this mesh is constituted by only quadratic cells.
4922 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4923 * \throw If the coordinates array is not set.
4924 * \throw If the nodal connectivity of cells is not defined.
4926 bool MEDCouplingUMesh::isFullyQuadratic() const
4928 checkFullyDefined();
4930 int nbOfCells=getNumberOfCells();
4931 for(int i=0;i<nbOfCells && ret;i++)
4933 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4934 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4935 ret=cm.isQuadratic();
4941 * Checks if \a this mesh includes any quadratic cell.
4942 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4943 * \throw If the coordinates array is not set.
4944 * \throw If the nodal connectivity of cells is not defined.
4946 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4948 checkFullyDefined();
4950 int nbOfCells=getNumberOfCells();
4951 for(int i=0;i<nbOfCells && !ret;i++)
4953 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4954 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4955 ret=cm.isQuadratic();
4961 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4962 * this mesh, it remains unchanged.
4963 * \throw If the coordinates array is not set.
4964 * \throw If the nodal connectivity of cells is not defined.
4966 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4968 checkFullyDefined();
4969 int nbOfCells=getNumberOfCells();
4971 for(int i=0;i<nbOfCells;i++)
4973 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4974 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4975 if(cm.isQuadratic())
4977 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4978 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4979 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4985 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4986 newConn->alloc(getMeshLength()-delta,1);
4987 newConnI->alloc(nbOfCells+1,1);
4988 const int *icptr=_nodal_connec->getConstPointer();
4989 const int *iciptr=_nodal_connec_index->getConstPointer();
4990 int *ocptr=newConn->getPointer();
4991 int *ociptr=newConnI->getPointer();
4994 for(int i=0;i<nbOfCells;i++,ociptr++)
4996 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4997 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4998 if(!cm.isQuadratic())
5000 _types.insert(type);
5001 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5002 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5006 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5007 _types.insert(typel);
5008 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5009 int newNbOfNodes=cml.getNumberOfNodes();
5010 *ocptr++=(int)typel;
5011 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5012 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5015 setConnectivity(newConn,newConnI,false);
5019 * This method converts all linear cell in \a this to quadratic one.
5020 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5021 * 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)
5022 * 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.
5023 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5024 * end of the existing coordinates.
5026 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5027 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5028 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5030 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5032 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5034 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
5036 DataArrayInt *conn=0,*connI=0;
5037 DataArrayDouble *coords=0;
5038 std::set<INTERP_KERNEL::NormalizedCellType> types;
5039 checkFullyDefined();
5040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5041 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5042 int meshDim=getMeshDimension();
5043 switch(conversionType)
5049 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5050 connSafe=conn; connISafe=connI; coordsSafe=coords;
5053 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5054 connSafe=conn; connISafe=connI; coordsSafe=coords;
5057 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5058 connSafe=conn; connISafe=connI; coordsSafe=coords;
5061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5069 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5070 connSafe=conn; connISafe=connI; coordsSafe=coords;
5073 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5074 connSafe=conn; connISafe=connI; coordsSafe=coords;
5077 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5078 connSafe=conn; connISafe=connI; coordsSafe=coords;
5081 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5086 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5088 setConnectivity(connSafe,connISafe,false);
5090 setCoords(coordsSafe);
5095 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5096 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5097 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5099 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5101 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5105 int nbOfCells=getNumberOfCells();
5106 int nbOfNodes=getNumberOfNodes();
5107 const int *cPtr=_nodal_connec->getConstPointer();
5108 const int *icPtr=_nodal_connec_index->getConstPointer();
5109 int lastVal=0,offset=nbOfNodes;
5110 for(int i=0;i<nbOfCells;i++,icPtr++)
5112 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5113 if(type==INTERP_KERNEL::NORM_SEG2)
5115 types.insert(INTERP_KERNEL::NORM_SEG3);
5116 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5117 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5118 newConn->pushBackSilent(offset++);
5120 newConnI->pushBackSilent(lastVal);
5121 ret->pushBackSilent(i);
5126 lastVal+=(icPtr[1]-icPtr[0]);
5127 newConnI->pushBackSilent(lastVal);
5128 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5131 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5132 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5136 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)
5138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5139 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5140 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5142 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5143 DataArrayInt *conn1D=0,*conn1DI=0;
5144 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5145 DataArrayDouble *coordsTmp=0;
5146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5147 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5148 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5149 const int *c1DPtr=conn1D->begin();
5150 const int *c1DIPtr=conn1DI->begin();
5151 int nbOfCells=getNumberOfCells();
5152 const int *cPtr=_nodal_connec->getConstPointer();
5153 const int *icPtr=_nodal_connec_index->getConstPointer();
5155 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5157 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5158 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5159 if(!cm.isQuadratic())
5161 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5162 types.insert(typ2); newConn->pushBackSilent(typ2);
5163 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5164 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5165 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5166 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5167 newConnI->pushBackSilent(lastVal);
5168 ret->pushBackSilent(i);
5173 lastVal+=(icPtr[1]-icPtr[0]);
5174 newConnI->pushBackSilent(lastVal);
5175 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5178 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5183 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5184 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5185 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5187 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5190 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5191 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5192 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5195 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5198 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5202 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5204 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5205 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5206 DataArrayInt *conn1D=0,*conn1DI=0;
5207 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5208 DataArrayDouble *coordsTmp=0;
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5210 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5212 const int *c1DPtr=conn1D->begin();
5213 const int *c1DIPtr=conn1DI->begin();
5214 int nbOfCells=getNumberOfCells();
5215 const int *cPtr=_nodal_connec->getConstPointer();
5216 const int *icPtr=_nodal_connec_index->getConstPointer();
5217 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5218 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5220 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5221 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5222 if(!cm.isQuadratic())
5224 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5225 types.insert(typ2); newConn->pushBackSilent(typ2);
5226 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5227 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5228 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5229 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5230 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5231 newConnI->pushBackSilent(lastVal);
5232 ret->pushBackSilent(i);
5237 lastVal+=(icPtr[1]-icPtr[0]);
5238 newConnI->pushBackSilent(lastVal);
5239 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5243 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5248 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5249 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5250 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5252 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5255 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5256 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5259 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5262 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5264 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5271 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5272 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5273 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5274 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5277 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5281 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5282 int nbOfCells=getNumberOfCells();
5283 const int *cPtr=_nodal_connec->getConstPointer();
5284 const int *icPtr=_nodal_connec_index->getConstPointer();
5285 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5286 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5288 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5289 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5290 if(!cm.isQuadratic())
5292 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5293 if(typ2==INTERP_KERNEL::NORM_ERROR)
5295 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5296 throw INTERP_KERNEL::Exception(oss.str().c_str());
5298 types.insert(typ2); newConn->pushBackSilent(typ2);
5299 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5300 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5301 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5302 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5304 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5305 int tmpPos=newConn->getNumberOfTuples();
5306 newConn->pushBackSilent(nodeId2);
5307 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5309 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5310 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5311 newConnI->pushBackSilent(lastVal);
5312 ret->pushBackSilent(i);
5317 lastVal+=(icPtr[1]-icPtr[0]);
5318 newConnI->pushBackSilent(lastVal);
5319 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5324 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5325 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5326 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5327 int *c=newConn->getPointer();
5328 const int *cI(newConnI->begin());
5329 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5330 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5331 offset=coordsTmp2Safe->getNumberOfTuples();
5332 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5333 c[cI[(*elt)+1]-1]+=offset;
5334 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5339 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5340 * so that the number of cells remains the same. Quadratic faces are converted to
5341 * polygons. This method works only for 2D meshes in
5342 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5343 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5344 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5345 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5346 * a polylinized edge constituting the input polygon.
5347 * \throw If the coordinates array is not set.
5348 * \throw If the nodal connectivity of cells is not defined.
5349 * \throw If \a this->getMeshDimension() != 2.
5350 * \throw If \a this->getSpaceDimension() != 2.
5352 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5354 checkFullyDefined();
5355 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5356 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5357 double epsa=fabs(eps);
5358 if(epsa<std::numeric_limits<double>::min())
5359 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 !");
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5364 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5365 revDesc1=0; revDescIndx1=0;
5366 mDesc->tessellate2DCurve(eps);
5367 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5368 setCoords(mDesc->getCoords());
5372 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5373 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5374 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5375 * a sub-divided edge.
5376 * \throw If the coordinates array is not set.
5377 * \throw If the nodal connectivity of cells is not defined.
5378 * \throw If \a this->getMeshDimension() != 1.
5379 * \throw If \a this->getSpaceDimension() != 2.
5381 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5383 checkFullyDefined();
5384 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5385 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5386 double epsa=fabs(eps);
5387 if(epsa<std::numeric_limits<double>::min())
5388 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 !");
5389 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5390 int nbCells=getNumberOfCells();
5391 int nbNodes=getNumberOfNodes();
5392 const int *conn=_nodal_connec->getConstPointer();
5393 const int *connI=_nodal_connec_index->getConstPointer();
5394 const double *coords=_coords->getConstPointer();
5395 std::vector<double> addCoo;
5396 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5397 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5398 newConnI->alloc(nbCells+1,1);
5399 int *newConnIPtr=newConnI->getPointer();
5402 INTERP_KERNEL::Node *tmp2[3];
5403 std::set<INTERP_KERNEL::NormalizedCellType> types;
5404 for(int i=0;i<nbCells;i++,newConnIPtr++)
5406 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5407 if(cm.isQuadratic())
5408 {//assert(connI[i+1]-connI[i]-1==3)
5409 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5410 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5411 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5412 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5413 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5416 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5417 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5419 newConnIPtr[1]=(int)newConn.size();
5423 types.insert(INTERP_KERNEL::NORM_SEG2);
5424 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5425 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5426 newConnIPtr[1]=newConnIPtr[0]+3;
5431 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5432 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5433 newConnIPtr[1]=newConnIPtr[0]+3;
5436 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5439 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5440 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5441 newConnArr->alloc((int)newConn.size(),1);
5442 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5443 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5444 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5445 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5446 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5447 std::copy(addCoo.begin(),addCoo.end(),work);
5448 DataArrayDouble::SetArrayIn(newCoords,_coords);
5453 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5454 * In addition, returns an array mapping new cells to old ones. <br>
5455 * This method typically increases the number of cells in \a this mesh
5456 * but the number of nodes remains \b unchanged.
5457 * That's why the 3D splitting policies
5458 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5459 * \param [in] policy - specifies a pattern used for splitting.
5460 * The semantic of \a policy is:
5461 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5462 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5463 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5464 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5465 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5466 * an id of old cell producing it. The caller is to delete this array using
5467 * decrRef() as it is no more needed.
5468 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5469 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5470 * and \a this->getMeshDimension() != 3.
5471 * \throw If \a policy is not one of the four discussed above.
5472 * \throw If the nodal connectivity of cells is not defined.
5474 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5479 return simplexizePol0();
5481 return simplexizePol1();
5482 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5483 return simplexizePlanarFace5();
5484 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5485 return simplexizePlanarFace6();
5487 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)");
5492 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5493 * - 1D: INTERP_KERNEL::NORM_SEG2
5494 * - 2D: INTERP_KERNEL::NORM_TRI3
5495 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5497 * This method is useful for users that need to use P1 field services as
5498 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5499 * All these methods need mesh support containing only simplex cells.
5500 * \return bool - \c true if there are only simplex cells in \a this mesh.
5501 * \throw If the coordinates array is not set.
5502 * \throw If the nodal connectivity of cells is not defined.
5503 * \throw If \a this->getMeshDimension() < 1.
5505 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5507 checkFullyDefined();
5508 int mdim=getMeshDimension();
5509 if(mdim<1 || mdim>3)
5510 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5511 int nbCells=getNumberOfCells();
5512 const int *conn=_nodal_connec->getConstPointer();
5513 const int *connI=_nodal_connec_index->getConstPointer();
5514 for(int i=0;i<nbCells;i++)
5516 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5524 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5526 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5528 checkConnectivityFullyDefined();
5529 if(getMeshDimension()!=2)
5530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5531 int nbOfCells=getNumberOfCells();
5532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5533 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5534 ret->alloc(nbOfCells+nbOfCutCells,1);
5535 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5536 int *retPt=ret->getPointer();
5537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5539 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5540 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5541 int *pt=newConn->getPointer();
5542 int *ptI=newConnI->getPointer();
5544 const int *oldc=_nodal_connec->getConstPointer();
5545 const int *ci=_nodal_connec_index->getConstPointer();
5546 for(int i=0;i<nbOfCells;i++,ci++)
5548 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5550 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5551 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5552 pt=std::copy(tmp,tmp+8,pt);
5561 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5562 ptI[1]=ptI[0]+ci[1]-ci[0];
5567 _nodal_connec->decrRef();
5568 _nodal_connec=newConn.retn();
5569 _nodal_connec_index->decrRef();
5570 _nodal_connec_index=newConnI.retn();
5577 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5579 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5581 checkConnectivityFullyDefined();
5582 if(getMeshDimension()!=2)
5583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5584 int nbOfCells=getNumberOfCells();
5585 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5586 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5587 ret->alloc(nbOfCells+nbOfCutCells,1);
5588 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5589 int *retPt=ret->getPointer();
5590 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5591 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5592 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5593 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5594 int *pt=newConn->getPointer();
5595 int *ptI=newConnI->getPointer();
5597 const int *oldc=_nodal_connec->getConstPointer();
5598 const int *ci=_nodal_connec_index->getConstPointer();
5599 for(int i=0;i<nbOfCells;i++,ci++)
5601 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5603 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5604 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5605 pt=std::copy(tmp,tmp+8,pt);
5614 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5615 ptI[1]=ptI[0]+ci[1]-ci[0];
5620 _nodal_connec->decrRef();
5621 _nodal_connec=newConn.retn();
5622 _nodal_connec_index->decrRef();
5623 _nodal_connec_index=newConnI.retn();
5630 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5632 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5634 checkConnectivityFullyDefined();
5635 if(getMeshDimension()!=3)
5636 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5637 int nbOfCells=getNumberOfCells();
5638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5639 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5640 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5641 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5642 int *retPt=ret->getPointer();
5643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5645 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5646 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5647 int *pt=newConn->getPointer();
5648 int *ptI=newConnI->getPointer();
5650 const int *oldc=_nodal_connec->getConstPointer();
5651 const int *ci=_nodal_connec_index->getConstPointer();
5652 for(int i=0;i<nbOfCells;i++,ci++)
5654 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5656 for(int j=0;j<5;j++,pt+=5,ptI++)
5658 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5659 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];
5666 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5667 ptI[1]=ptI[0]+ci[1]-ci[0];
5672 _nodal_connec->decrRef();
5673 _nodal_connec=newConn.retn();
5674 _nodal_connec_index->decrRef();
5675 _nodal_connec_index=newConnI.retn();
5682 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5684 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5686 checkConnectivityFullyDefined();
5687 if(getMeshDimension()!=3)
5688 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5689 int nbOfCells=getNumberOfCells();
5690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5691 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5692 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5693 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5694 int *retPt=ret->getPointer();
5695 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5696 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5697 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5698 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5699 int *pt=newConn->getPointer();
5700 int *ptI=newConnI->getPointer();
5702 const int *oldc=_nodal_connec->getConstPointer();
5703 const int *ci=_nodal_connec_index->getConstPointer();
5704 for(int i=0;i<nbOfCells;i++,ci++)
5706 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5708 for(int j=0;j<6;j++,pt+=5,ptI++)
5710 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5711 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];
5718 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5719 ptI[1]=ptI[0]+ci[1]-ci[0];
5724 _nodal_connec->decrRef();
5725 _nodal_connec=newConn.retn();
5726 _nodal_connec_index->decrRef();
5727 _nodal_connec_index=newConnI.retn();
5734 * This private method is used to subdivide edges of a mesh with meshdim==2. If 'this' has no a meshdim equal to 2 an exception will be thrown.
5735 * This method completly ignore coordinates.
5736 * @param nodeSubdived is the nodal connectivity of subdivision of edges
5737 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5738 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5739 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5741 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5743 checkFullyDefined();
5744 if(getMeshDimension()!=2)
5745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5746 int nbOfCells=getNumberOfCells();
5747 int *connI=_nodal_connec_index->getPointer();
5749 for(int i=0;i<nbOfCells;i++,connI++)
5751 int offset=descIndex[i];
5752 int nbOfEdges=descIndex[i+1]-offset;
5754 bool ddirect=desc[offset+nbOfEdges-1]>0;
5755 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5756 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5757 for(int j=0;j<nbOfEdges;j++)
5759 bool direct=desc[offset+j]>0;
5760 int edgeId=std::abs(desc[offset+j])-1;
5761 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5763 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5764 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5765 int ref2=direct?id1:id2;
5768 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5769 newConnLgth+=nbOfSubNodes-1;
5774 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5775 throw INTERP_KERNEL::Exception(oss.str().c_str());
5780 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5783 newConnLgth++;//+1 is for cell type
5784 connI[1]=newConnLgth;
5787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5788 newConn->alloc(newConnLgth,1);
5789 int *work=newConn->getPointer();
5790 for(int i=0;i<nbOfCells;i++)
5792 *work++=INTERP_KERNEL::NORM_POLYGON;
5793 int offset=descIndex[i];
5794 int nbOfEdges=descIndex[i+1]-offset;
5795 for(int j=0;j<nbOfEdges;j++)
5797 bool direct=desc[offset+j]>0;
5798 int edgeId=std::abs(desc[offset+j])-1;
5800 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5803 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5804 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5805 work=std::copy(it,it+nbOfSubNodes-1,work);
5809 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5812 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5816 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5817 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5818 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5819 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5820 * so it can be useful to call mergeNodes() before calling this method.
5821 * \throw If \a this->getMeshDimension() <= 1.
5822 * \throw If the coordinates array is not set.
5823 * \throw If the nodal connectivity of cells is not defined.
5825 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5827 checkFullyDefined();
5828 if(getMeshDimension()<=1)
5829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5830 int nbOfCells=getNumberOfCells();
5833 int initMeshLgth=getMeshLength();
5834 int *conn=_nodal_connec->getPointer();
5835 int *index=_nodal_connec_index->getPointer();
5839 for(int i=0;i<nbOfCells;i++)
5841 lgthOfCurCell=index[i+1]-posOfCurCell;
5842 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5844 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5845 conn+newPos+1,newLgth);
5846 conn[newPos]=newType;
5848 posOfCurCell=index[i+1];
5851 if(newPos!=initMeshLgth)
5852 _nodal_connec->reAlloc(newPos);
5857 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5858 * A cell is considered to be oriented correctly if an angle between its
5859 * normal vector and a given vector is less than \c PI / \c 2.
5860 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5862 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5864 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5865 * is not cleared before filling in.
5866 * \throw If \a this->getMeshDimension() != 2.
5867 * \throw If \a this->getSpaceDimension() != 3.
5869 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5870 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5872 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5874 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5875 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5876 int nbOfCells=getNumberOfCells();
5877 const int *conn=_nodal_connec->getConstPointer();
5878 const int *connI=_nodal_connec_index->getConstPointer();
5879 const double *coordsPtr=_coords->getConstPointer();
5880 for(int i=0;i<nbOfCells;i++)
5882 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5883 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5885 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5886 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5893 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5894 * considered to be oriented correctly if an angle between its normal vector and a
5895 * given vector is less than \c PI / \c 2.
5896 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5898 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5900 * \throw If \a this->getMeshDimension() != 2.
5901 * \throw If \a this->getSpaceDimension() != 3.
5903 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5904 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5906 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5908 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5909 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5910 int nbOfCells=getNumberOfCells();
5911 int *conn=_nodal_connec->getPointer();
5912 const int *connI=_nodal_connec_index->getConstPointer();
5913 const double *coordsPtr=_coords->getConstPointer();
5914 bool isModified=false;
5915 for(int i=0;i<nbOfCells;i++)
5917 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5918 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5920 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5921 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5924 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5925 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5926 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5931 _nodal_connec->declareAsNew();
5936 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5937 * oriented facets. The normal vector of the facet should point out of the cell.
5938 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5939 * is not cleared before filling in.
5940 * \throw If \a this->getMeshDimension() != 3.
5941 * \throw If \a this->getSpaceDimension() != 3.
5942 * \throw If the coordinates array is not set.
5943 * \throw If the nodal connectivity of cells is not defined.
5945 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5946 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5948 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5950 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5951 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5952 int nbOfCells=getNumberOfCells();
5953 const int *conn=_nodal_connec->getConstPointer();
5954 const int *connI=_nodal_connec_index->getConstPointer();
5955 const double *coordsPtr=_coords->getConstPointer();
5956 for(int i=0;i<nbOfCells;i++)
5958 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5959 if(type==INTERP_KERNEL::NORM_POLYHED)
5961 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5968 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5970 * \throw If \a this->getMeshDimension() != 3.
5971 * \throw If \a this->getSpaceDimension() != 3.
5972 * \throw If the coordinates array is not set.
5973 * \throw If the nodal connectivity of cells is not defined.
5974 * \throw If the reparation fails.
5976 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5977 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5978 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5980 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5982 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5983 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5984 int nbOfCells=getNumberOfCells();
5985 int *conn=_nodal_connec->getPointer();
5986 const int *connI=_nodal_connec_index->getConstPointer();
5987 const double *coordsPtr=_coords->getConstPointer();
5988 for(int i=0;i<nbOfCells;i++)
5990 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5991 if(type==INTERP_KERNEL::NORM_POLYHED)
5995 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5996 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5998 catch(INTERP_KERNEL::Exception& e)
6000 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6001 throw INTERP_KERNEL::Exception(oss.str().c_str());
6009 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6010 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6011 * according to which the first facet of the cell should be oriented to have the normal vector
6012 * pointing out of cell.
6013 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6014 * cells. The caller is to delete this array using decrRef() as it is no more
6016 * \throw If \a this->getMeshDimension() != 3.
6017 * \throw If \a this->getSpaceDimension() != 3.
6018 * \throw If the coordinates array is not set.
6019 * \throw If the nodal connectivity of cells is not defined.
6021 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6022 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6023 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6025 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
6027 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6028 if(getMeshDimension()!=3)
6029 throw INTERP_KERNEL::Exception(msg);
6030 int spaceDim=getSpaceDimension();
6032 throw INTERP_KERNEL::Exception(msg);
6034 int nbOfCells=getNumberOfCells();
6035 int *conn=_nodal_connec->getPointer();
6036 const int *connI=_nodal_connec_index->getConstPointer();
6037 const double *coo=getCoords()->getConstPointer();
6038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6039 for(int i=0;i<nbOfCells;i++)
6041 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6042 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6044 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6046 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6047 cells->pushBackSilent(i);
6051 return cells.retn();
6055 * This method is a faster method to correct orientation of all 3D cells in \a this.
6056 * 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.
6057 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6059 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6060 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6062 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
6064 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6065 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6066 int nbOfCells=getNumberOfCells();
6067 int *conn=_nodal_connec->getPointer();
6068 const int *connI=_nodal_connec_index->getConstPointer();
6069 const double *coordsPtr=_coords->getConstPointer();
6070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6071 for(int i=0;i<nbOfCells;i++)
6073 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6076 case INTERP_KERNEL::NORM_TETRA4:
6078 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6080 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6081 ret->pushBackSilent(i);
6085 case INTERP_KERNEL::NORM_PYRA5:
6087 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6089 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6090 ret->pushBackSilent(i);
6094 case INTERP_KERNEL::NORM_PENTA6:
6095 case INTERP_KERNEL::NORM_HEXA8:
6096 case INTERP_KERNEL::NORM_HEXGP12:
6098 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6100 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6101 ret->pushBackSilent(i);
6105 case INTERP_KERNEL::NORM_POLYHED:
6107 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6109 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6110 ret->pushBackSilent(i);
6115 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 !");
6123 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6124 * If it is not the case an exception will be thrown.
6125 * This method is fast because the first cell of 'this' is used to compute the plane.
6126 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6127 * @param pos output of size at least 3 used to store a point owned of searched plane.
6129 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
6131 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6132 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6133 const int *conn=_nodal_connec->getConstPointer();
6134 const int *connI=_nodal_connec_index->getConstPointer();
6135 const double *coordsPtr=_coords->getConstPointer();
6136 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6137 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6141 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6142 * cells. Currently cells of the following types are treated:
6143 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6144 * For a cell of other type an exception is thrown.
6145 * Space dimension of a 2D mesh can be either 2 or 3.
6146 * The Edge Ratio of a cell \f$t\f$ is:
6147 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6148 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6149 * the smallest edge lengths of \f$t\f$.
6150 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6151 * cells and one time, lying on \a this mesh. The caller is to delete this
6152 * field using decrRef() as it is no more needed.
6153 * \throw If the coordinates array is not set.
6154 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6155 * \throw If the connectivity data array has more than one component.
6156 * \throw If the connectivity data array has a named component.
6157 * \throw If the connectivity index data array has more than one component.
6158 * \throw If the connectivity index data array has a named component.
6159 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6160 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6161 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6163 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
6166 int spaceDim=getSpaceDimension();
6167 int meshDim=getMeshDimension();
6168 if(spaceDim!=2 && spaceDim!=3)
6169 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6170 if(meshDim!=2 && meshDim!=3)
6171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6172 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6174 int nbOfCells=getNumberOfCells();
6175 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6176 arr->alloc(nbOfCells,1);
6177 double *pt=arr->getPointer();
6178 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6179 const int *conn=_nodal_connec->getConstPointer();
6180 const int *connI=_nodal_connec_index->getConstPointer();
6181 const double *coo=_coords->getConstPointer();
6183 for(int i=0;i<nbOfCells;i++,pt++)
6185 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6188 case INTERP_KERNEL::NORM_TRI3:
6190 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6191 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6194 case INTERP_KERNEL::NORM_QUAD4:
6196 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6197 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6200 case INTERP_KERNEL::NORM_TETRA4:
6202 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6203 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6209 conn+=connI[i+1]-connI[i];
6211 ret->setName("EdgeRatio");
6212 ret->synchronizeTimeWithSupport();
6217 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6218 * cells. Currently cells of the following types are treated:
6219 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6220 * For a cell of other type an exception is thrown.
6221 * Space dimension of a 2D mesh can be either 2 or 3.
6222 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6223 * cells and one time, lying on \a this mesh. The caller is to delete this
6224 * field using decrRef() as it is no more needed.
6225 * \throw If the coordinates array is not set.
6226 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6227 * \throw If the connectivity data array has more than one component.
6228 * \throw If the connectivity data array has a named component.
6229 * \throw If the connectivity index data array has more than one component.
6230 * \throw If the connectivity index data array has a named component.
6231 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6232 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6233 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6235 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6238 int spaceDim=getSpaceDimension();
6239 int meshDim=getMeshDimension();
6240 if(spaceDim!=2 && spaceDim!=3)
6241 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6242 if(meshDim!=2 && meshDim!=3)
6243 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6244 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6246 int nbOfCells=getNumberOfCells();
6247 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6248 arr->alloc(nbOfCells,1);
6249 double *pt=arr->getPointer();
6250 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6251 const int *conn=_nodal_connec->getConstPointer();
6252 const int *connI=_nodal_connec_index->getConstPointer();
6253 const double *coo=_coords->getConstPointer();
6255 for(int i=0;i<nbOfCells;i++,pt++)
6257 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6260 case INTERP_KERNEL::NORM_TRI3:
6262 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6263 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6266 case INTERP_KERNEL::NORM_QUAD4:
6268 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6269 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6272 case INTERP_KERNEL::NORM_TETRA4:
6274 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6275 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6281 conn+=connI[i+1]-connI[i];
6283 ret->setName("AspectRatio");
6284 ret->synchronizeTimeWithSupport();
6289 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6290 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6291 * treated: INTERP_KERNEL::NORM_QUAD4.
6292 * For a cell of other type an exception is thrown.
6293 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6294 * cells and one time, lying on \a this mesh. The caller is to delete this
6295 * field using decrRef() as it is no more needed.
6296 * \throw If the coordinates array is not set.
6297 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6298 * \throw If the connectivity data array has more than one component.
6299 * \throw If the connectivity data array has a named component.
6300 * \throw If the connectivity index data array has more than one component.
6301 * \throw If the connectivity index data array has a named component.
6302 * \throw If \a this->getMeshDimension() != 2.
6303 * \throw If \a this->getSpaceDimension() != 3.
6304 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6306 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6309 int spaceDim=getSpaceDimension();
6310 int meshDim=getMeshDimension();
6312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6314 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6315 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6317 int nbOfCells=getNumberOfCells();
6318 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6319 arr->alloc(nbOfCells,1);
6320 double *pt=arr->getPointer();
6321 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6322 const int *conn=_nodal_connec->getConstPointer();
6323 const int *connI=_nodal_connec_index->getConstPointer();
6324 const double *coo=_coords->getConstPointer();
6326 for(int i=0;i<nbOfCells;i++,pt++)
6328 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6331 case INTERP_KERNEL::NORM_QUAD4:
6333 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6334 *pt=INTERP_KERNEL::quadWarp(tmp);
6338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6340 conn+=connI[i+1]-connI[i];
6342 ret->setName("Warp");
6343 ret->synchronizeTimeWithSupport();
6349 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6350 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6351 * treated: INTERP_KERNEL::NORM_QUAD4.
6352 * For a cell of other type an exception is thrown.
6353 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6354 * cells and one time, lying on \a this mesh. The caller is to delete this
6355 * field using decrRef() as it is no more needed.
6356 * \throw If the coordinates array is not set.
6357 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6358 * \throw If the connectivity data array has more than one component.
6359 * \throw If the connectivity data array has a named component.
6360 * \throw If the connectivity index data array has more than one component.
6361 * \throw If the connectivity index data array has a named component.
6362 * \throw If \a this->getMeshDimension() != 2.
6363 * \throw If \a this->getSpaceDimension() != 3.
6364 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6366 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6369 int spaceDim=getSpaceDimension();
6370 int meshDim=getMeshDimension();
6372 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6374 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6375 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6377 int nbOfCells=getNumberOfCells();
6378 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6379 arr->alloc(nbOfCells,1);
6380 double *pt=arr->getPointer();
6381 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6382 const int *conn=_nodal_connec->getConstPointer();
6383 const int *connI=_nodal_connec_index->getConstPointer();
6384 const double *coo=_coords->getConstPointer();
6386 for(int i=0;i<nbOfCells;i++,pt++)
6388 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6391 case INTERP_KERNEL::NORM_QUAD4:
6393 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6394 *pt=INTERP_KERNEL::quadSkew(tmp);
6398 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6400 conn+=connI[i+1]-connI[i];
6402 ret->setName("Skew");
6403 ret->synchronizeTimeWithSupport();
6408 * This method aggregate the bbox of each cell and put it into bbox parameter.
6409 * @param bbox out parameter of size 2*spacedim*nbOfcells.
6411 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6413 int spaceDim=getSpaceDimension();
6414 int nbOfCells=getNumberOfCells();
6415 bbox.resize(2*nbOfCells*spaceDim);
6416 for(int i=0;i<nbOfCells*spaceDim;i++)
6418 bbox[2*i]=std::numeric_limits<double>::max();
6419 bbox[2*i+1]=-std::numeric_limits<double>::max();
6421 const double *coordsPtr=_coords->getConstPointer();
6422 const int *conn=_nodal_connec->getConstPointer();
6423 const int *connI=_nodal_connec_index->getConstPointer();
6424 for(int i=0;i<nbOfCells;i++)
6426 int offset=connI[i]+1;
6427 int nbOfNodesForCell=connI[i+1]-offset;
6428 for(int j=0;j<nbOfNodesForCell;j++)
6430 int nodeId=conn[offset+j];
6432 for(int k=0;k<spaceDim;k++)
6434 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6435 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6443 namespace ParaMEDMEMImpl
6448 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6449 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6458 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6459 bool operator() (const int& pos) { return _conn[pos]==_val; }
6469 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
6470 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6471 * 'this' is composed in cell types.
6472 * The returned array is of size 3*n where n is the number of different types present in 'this'.
6473 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
6474 * This parameter is kept only for compatibility with other methode listed above.
6476 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6478 checkConnectivityFullyDefined();
6479 const int *conn=_nodal_connec->getConstPointer();
6480 const int *connI=_nodal_connec_index->getConstPointer();
6481 const int *work=connI;
6482 int nbOfCells=getNumberOfCells();
6483 std::size_t n=getAllTypes().size();
6484 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6485 std::set<INTERP_KERNEL::NormalizedCellType> types;
6486 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6488 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6489 if(types.find(typ)!=types.end())
6491 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6492 oss << " is not contiguous !";
6493 throw INTERP_KERNEL::Exception(oss.str().c_str());
6497 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6498 ret[3*i+1]=(int)std::distance(work,work2);
6505 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
6506 * only for types cell, type node is not managed.
6507 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
6508 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6509 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6510 * If 2 or more same geometric type is in 'code' and exception is thrown too.
6512 * This method firstly checks
6513 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6514 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6515 * an exception is thrown too.
6517 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
6518 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
6519 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6521 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6524 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6525 std::size_t sz=code.size();
6528 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6529 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6531 for(std::size_t i=0;i<n;i++)
6532 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6534 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6536 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6537 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6540 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6541 if(idsPerType.empty())
6543 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6544 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6545 if(types.size()==_types.size())
6548 DataArrayInt *ret=DataArrayInt::New();
6550 int *retPtr=ret->getPointer();
6551 const int *connI=_nodal_connec_index->getConstPointer();
6552 const int *conn=_nodal_connec->getConstPointer();
6553 int nbOfCells=getNumberOfCells();
6556 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6558 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6559 int offset=(int)std::distance(connI,i);
6560 if(code[3*kk+2]==-1)
6562 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6563 std::size_t pos2=std::distance(i,j);
6564 for(std::size_t k=0;k<pos2;k++)
6565 *retPtr++=(int)k+offset;
6570 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6571 retPtr,std::bind2nd(std::plus<int>(),offset));
6578 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6579 * 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.
6580 * 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.
6581 * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
6583 * @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.
6584 * @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,
6585 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6586 * @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.
6587 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6588 * @throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
6590 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6592 if(profile->getNumberOfComponents()!=1)
6593 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6594 checkConnectivityFullyDefined();
6595 const int *conn=_nodal_connec->getConstPointer();
6596 const int *connI=_nodal_connec_index->getConstPointer();
6597 int nbOfCells=getNumberOfCells();
6598 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6599 std::vector<int> typeRangeVals(1);
6600 for(const int *i=connI;i!=connI+nbOfCells;)
6602 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6603 if(std::find(types.begin(),types.end(),curType)!=types.end())
6605 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6607 types.push_back(curType);
6608 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6609 typeRangeVals.push_back((int)std::distance(connI,i));
6612 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6613 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6614 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6618 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6619 code.resize(3*nbOfCastsFinal);
6620 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6621 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6622 for(int i=0;i<nbOfCastsFinal;i++)
6624 int castId=castsPresent->getIJ(i,0);
6625 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6626 idsInPflPerType2.push_back(tmp3);
6627 code[3*i]=(int)types[castId];
6628 code[3*i+1]=tmp3->getNumberOfTuples();
6629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6630 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6632 tmp4->copyStringInfoFrom(*profile);
6633 idsPerType2.push_back(tmp4);
6634 code[3*i+2]=(int)idsPerType2.size()-1;
6641 std::size_t sz2=idsInPflPerType2.size();
6642 idsInPflPerType.resize(sz2);
6643 for(std::size_t i=0;i<sz2;i++)
6645 DataArrayInt *locDa=idsInPflPerType2[i];
6647 idsInPflPerType[i]=locDa;
6649 std::size_t sz=idsPerType2.size();
6650 idsPerType.resize(sz);
6651 for(std::size_t i=0;i<sz;i++)
6653 DataArrayInt *locDa=idsPerType2[i];
6655 idsPerType[i]=locDa;
6660 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6661 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6662 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6663 * 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.
6665 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6667 checkFullyDefined();
6668 nM1LevMesh->checkFullyDefined();
6669 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6670 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6671 if(_coords!=nM1LevMesh->getCoords())
6672 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6673 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6674 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6675 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6677 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6678 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6679 tmp->setConnectivity(tmp0,tmp1);
6680 tmp->renumberCells(ret0->getConstPointer(),false);
6681 revDesc=tmp->getNodalConnectivity();
6682 revDescIndx=tmp->getNodalConnectivityIndex();
6683 DataArrayInt *ret=0;
6684 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6687 ret->getMaxValue(tmp2);
6689 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6690 throw INTERP_KERNEL::Exception(oss.str().c_str());
6695 revDescIndx->incrRef();
6698 meshnM1Old2New=ret0;
6703 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6704 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6705 * in "Old to New" mode.
6706 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6707 * this array using decrRef() as it is no more needed.
6708 * \throw If the nodal connectivity of cells is not defined.
6710 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6712 checkConnectivityFullyDefined();
6713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6714 renumberCells(ret->getConstPointer(),false);
6719 * This methods checks that cells are sorted by their types.
6720 * This method makes asumption (no check) that connectivity is correctly set before calling.
6722 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6724 checkFullyDefined();
6725 const int *conn=_nodal_connec->getConstPointer();
6726 const int *connI=_nodal_connec_index->getConstPointer();
6727 int nbOfCells=getNumberOfCells();
6728 std::set<INTERP_KERNEL::NormalizedCellType> types;
6729 for(const int *i=connI;i!=connI+nbOfCells;)
6731 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6732 if(types.find(curType)!=types.end())
6734 types.insert(curType);
6735 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6741 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6742 * The geometric type order is specified by MED file.
6744 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6746 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6748 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6752 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6753 * that the order is specified in array defined by [orderBg,orderEnd).
6754 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6755 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6757 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6759 checkFullyDefined();
6760 const int *conn=_nodal_connec->getConstPointer();
6761 const int *connI=_nodal_connec_index->getConstPointer();
6762 int nbOfCells=getNumberOfCells();
6766 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6767 for(const int *i=connI;i!=connI+nbOfCells;)
6769 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6770 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6771 if(isTypeExists!=orderEnd)
6773 int pos=(int)std::distance(orderBg,isTypeExists);
6777 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6781 if(sg.find(curType)==sg.end())
6783 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6794 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6795 * 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
6796 * 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'.
6798 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6800 checkConnectivityFullyDefined();
6801 int nbOfCells=getNumberOfCells();
6802 const int *conn=_nodal_connec->getConstPointer();
6803 const int *connI=_nodal_connec_index->getConstPointer();
6804 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6805 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6806 tmpa->alloc(nbOfCells,1);
6807 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6808 tmpb->fillWithZero();
6809 int *tmp=tmpa->getPointer();
6810 int *tmp2=tmpb->getPointer();
6811 for(const int *i=connI;i!=connI+nbOfCells;i++)
6813 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6816 int pos=(int)std::distance(orderBg,where);
6818 tmp[std::distance(connI,i)]=pos;
6822 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6823 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6824 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6825 throw INTERP_KERNEL::Exception(oss.str().c_str());
6828 nbPerType=tmpb.retn();
6833 * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [orderBg,orderEnd) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in 'this'.
6834 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6835 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6836 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6838 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6840 DataArrayInt *nbPerType=0;
6841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6842 nbPerType->decrRef();
6843 return tmpa->buildPermArrPerLevel();
6847 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6848 * The number of cells remains unchanged after the call of this method.
6849 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6850 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6852 * @return the array giving the correspondance old to new.
6854 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6856 checkFullyDefined();
6858 const int *conn=_nodal_connec->getConstPointer();
6859 const int *connI=_nodal_connec_index->getConstPointer();
6860 int nbOfCells=getNumberOfCells();
6861 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6862 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6863 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6865 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6866 types.push_back(curType);
6867 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6869 DataArrayInt *ret=DataArrayInt::New();
6870 ret->alloc(nbOfCells,1);
6871 int *retPtr=ret->getPointer();
6872 std::fill(retPtr,retPtr+nbOfCells,-1);
6874 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6876 for(const int *i=connI;i!=connI+nbOfCells;i++)
6877 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6878 retPtr[std::distance(connI,i)]=newCellId++;
6880 renumberCells(retPtr,false);
6885 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6886 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6887 * This method makes asumption that connectivity is correctly set before calling.
6889 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6891 checkFullyDefined();
6892 const int *conn=_nodal_connec->getConstPointer();
6893 const int *connI=_nodal_connec_index->getConstPointer();
6894 int nbOfCells=getNumberOfCells();
6895 std::vector<MEDCouplingUMesh *> ret;
6896 for(const int *i=connI;i!=connI+nbOfCells;)
6898 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6899 int beginCellId=(int)std::distance(connI,i);
6900 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6901 int endCellId=(int)std::distance(connI,i);
6902 int sz=endCellId-beginCellId;
6903 int *cells=new int[sz];
6904 for(int j=0;j<sz;j++)
6905 cells[j]=beginCellId+j;
6906 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6914 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6915 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6916 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6917 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6918 * are not used here to avoid the build of big permutation array.
6920 * \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
6921 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6922 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6923 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6924 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6925 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6926 * \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
6927 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6929 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6930 DataArrayInt *&szOfCellGrpOfSameType,
6931 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6933 std::vector<const MEDCouplingUMesh *> ms2;
6934 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6937 (*it)->checkConnectivityFullyDefined();
6941 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6942 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6943 int meshDim=ms2[0]->getMeshDimension();
6944 std::vector<const MEDCouplingUMesh *> m1ssm;
6945 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6947 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6948 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6951 ret1->alloc(0,1); ret2->alloc(0,1);
6952 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6954 if(meshDim!=(*it)->getMeshDimension())
6955 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6956 if(refCoo!=(*it)->getCoords())
6957 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6958 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6959 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6960 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6961 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6963 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6964 m1ssmSingleAuto.push_back(singleCell);
6965 m1ssmSingle.push_back(singleCell);
6966 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6969 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6971 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6972 for(std::size_t i=0;i<m1ssm.size();i++)
6973 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6974 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6975 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6976 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6981 * This method returns a newly created DataArrayInt instance.
6982 * This method retrieves cell ids in [begin,end) that have the type 'type'.
6984 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6986 checkFullyDefined();
6987 const int *conn=_nodal_connec->getConstPointer();
6988 const int *connIndex=_nodal_connec_index->getConstPointer();
6989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6990 for(const int *w=begin;w!=end;w++)
6991 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6992 ret->pushBackSilent(*w);
6997 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6998 * are in [0:getNumberOfCells())
7000 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
7002 checkFullyDefined();
7003 const int *conn=_nodal_connec->getConstPointer();
7004 const int *connI=_nodal_connec_index->getConstPointer();
7005 int nbOfCells=getNumberOfCells();
7006 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
7007 int *tmp=new int[nbOfCells];
7008 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7011 for(const int *i=connI;i!=connI+nbOfCells;i++)
7012 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7013 tmp[std::distance(connI,i)]=j++;
7015 DataArrayInt *ret=DataArrayInt::New();
7016 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7017 ret->copyStringInfoFrom(*da);
7018 int *retPtr=ret->getPointer();
7019 const int *daPtr=da->getConstPointer();
7020 int nbOfElems=da->getNbOfElems();
7021 for(int k=0;k<nbOfElems;k++)
7022 retPtr[k]=tmp[daPtr[k]];
7028 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7029 * This method \b works \b for mesh sorted by type.
7030 * cells whose ids is in 'idsPerGeoType' array.
7031 * This method conserves coords and name of mesh.
7033 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7035 std::vector<int> code=getDistributionOfTypes();
7036 std::size_t nOfTypesInThis=code.size()/3;
7037 int sz=0,szOfType=0;
7038 for(std::size_t i=0;i<nOfTypesInThis;i++)
7043 szOfType=code[3*i+1];
7045 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7046 if(*work<0 || *work>=szOfType)
7048 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7049 oss << ". It should be in [0," << szOfType << ") !";
7050 throw INTERP_KERNEL::Exception(oss.str().c_str());
7052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7053 int *idsPtr=idsTokeep->getPointer();
7055 for(std::size_t i=0;i<nOfTypesInThis;i++)
7058 for(int j=0;j<code[3*i+1];j++)
7061 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7062 offset+=code[3*i+1];
7064 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7065 ret->copyTinyInfoFrom(this);
7070 * This method returns a vector of size 'this->getNumberOfCells()'.
7071 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
7073 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7075 int ncell=getNumberOfCells();
7076 std::vector<bool> ret(ncell);
7077 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7078 const int *c=getNodalConnectivity()->getConstPointer();
7079 for(int i=0;i<ncell;i++)
7081 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7082 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7083 ret[i]=cm.isQuadratic();
7089 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
7091 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7093 if(other->getType()!=UNSTRUCTURED)
7094 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7095 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7096 return MergeUMeshes(this,otherC);
7100 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7101 * computed by averaging coordinates of cell nodes, so this method is not a right
7102 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7103 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7104 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7105 * components. The caller is to delete this array using decrRef() as it is
7107 * \throw If the coordinates array is not set.
7108 * \throw If the nodal connectivity of cells is not defined.
7109 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7111 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7113 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7114 int spaceDim=getSpaceDimension();
7115 int nbOfCells=getNumberOfCells();
7116 ret->alloc(nbOfCells,spaceDim);
7117 ret->copyStringInfoFrom(*getCoords());
7118 double *ptToFill=ret->getPointer();
7119 const int *nodal=_nodal_connec->getConstPointer();
7120 const int *nodalI=_nodal_connec_index->getConstPointer();
7121 const double *coor=_coords->getConstPointer();
7122 for(int i=0;i<nbOfCells;i++)
7124 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7125 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7132 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7133 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7135 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7136 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7138 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7139 * \throw If \a this is not fully defined (coordinates and connectivity)
7140 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7142 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7144 checkFullyDefined();
7145 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7146 int spaceDim=getSpaceDimension();
7147 int nbOfCells=getNumberOfCells();
7148 int nbOfNodes=getNumberOfNodes();
7149 ret->alloc(nbOfCells,spaceDim);
7150 double *ptToFill=ret->getPointer();
7151 const int *nodal=_nodal_connec->getConstPointer();
7152 const int *nodalI=_nodal_connec_index->getConstPointer();
7153 const double *coor=_coords->getConstPointer();
7154 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7156 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7157 std::fill(ptToFill,ptToFill+spaceDim,0.);
7158 if(type!=INTERP_KERNEL::NORM_POLYHED)
7160 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7162 if(*conn>=0 && *conn<nbOfNodes)
7163 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7166 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7167 throw INTERP_KERNEL::Exception(oss.str().c_str());
7170 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7171 if(nbOfNodesInCell>0)
7172 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7175 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7176 throw INTERP_KERNEL::Exception(oss.str().c_str());
7181 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7183 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7185 if(*it>=0 && *it<nbOfNodes)
7186 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7189 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7190 throw INTERP_KERNEL::Exception(oss.str().c_str());
7194 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7197 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7198 throw INTERP_KERNEL::Exception(oss.str().c_str());
7206 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7207 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7208 * are specified via an array of cell ids.
7209 * \warning Validity of the specified cell ids is not checked!
7210 * Valid range is [ 0, \a this->getNumberOfCells() ).
7211 * \param [in] begin - an array of cell ids of interest.
7212 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7213 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7214 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7215 * caller is to delete this array using decrRef() as it is no more needed.
7216 * \throw If the coordinates array is not set.
7217 * \throw If the nodal connectivity of cells is not defined.
7219 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7220 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7222 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7224 DataArrayDouble *ret=DataArrayDouble::New();
7225 int spaceDim=getSpaceDimension();
7226 int nbOfTuple=(int)std::distance(begin,end);
7227 ret->alloc(nbOfTuple,spaceDim);
7228 double *ptToFill=ret->getPointer();
7229 double *tmp=new double[spaceDim];
7230 const int *nodal=_nodal_connec->getConstPointer();
7231 const int *nodalI=_nodal_connec_index->getConstPointer();
7232 const double *coor=_coords->getConstPointer();
7233 for(const int *w=begin;w!=end;w++)
7235 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7236 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7244 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7247 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7250 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7251 da->checkAllocated();
7252 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7254 int nbOfTuples=da->getNumberOfTuples();
7255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7256 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7257 c->alloc(2*nbOfTuples,1);
7258 cI->alloc(nbOfTuples+1,1);
7259 int *cp=c->getPointer();
7260 int *cip=cI->getPointer();
7262 for(int i=0;i<nbOfTuples;i++)
7264 *cp++=INTERP_KERNEL::NORM_POINT1;
7268 ret->setConnectivity(c,cI,true);
7272 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7273 * Cells and nodes of
7274 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7275 * \param [in] mesh1 - the first mesh.
7276 * \param [in] mesh2 - the second mesh.
7277 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7278 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7279 * is no more needed.
7280 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7281 * \throw If the coordinates array is not set in none of the meshes.
7282 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7283 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7285 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7287 std::vector<const MEDCouplingUMesh *> tmp(2);
7288 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7289 return MergeUMeshes(tmp);
7293 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7294 * Cells and nodes of
7295 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7296 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7297 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7298 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7299 * is no more needed.
7300 * \throw If \a a.size() == 0.
7301 * \throw If \a a[ *i* ] == NULL.
7302 * \throw If the coordinates array is not set in none of the meshes.
7303 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7304 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7306 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7308 std::size_t sz=a.size();
7310 return MergeUMeshesLL(a);
7311 for(std::size_t ii=0;ii<sz;ii++)
7314 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7315 throw INTERP_KERNEL::Exception(oss.str().c_str());
7317 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7318 std::vector< const MEDCouplingUMesh * > aa(sz);
7320 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7322 const MEDCouplingUMesh *cur=a[i];
7323 const DataArrayDouble *coo=cur->getCoords();
7325 spaceDim=coo->getNumberOfComponents();
7328 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7329 for(std::size_t i=0;i<sz;i++)
7331 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7334 return MergeUMeshesLL(aa);
7339 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7343 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7344 int meshDim=(*it)->getMeshDimension();
7345 int nbOfCells=(*it)->getNumberOfCells();
7346 int meshLgth=(*it++)->getMeshLength();
7347 for(;it!=a.end();it++)
7349 if(meshDim!=(*it)->getMeshDimension())
7350 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7351 nbOfCells+=(*it)->getNumberOfCells();
7352 meshLgth+=(*it)->getMeshLength();
7354 std::vector<const MEDCouplingPointSet *> aps(a.size());
7355 std::copy(a.begin(),a.end(),aps.begin());
7356 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7357 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7358 ret->setCoords(pts);
7359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7360 c->alloc(meshLgth,1);
7361 int *cPtr=c->getPointer();
7362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7363 cI->alloc(nbOfCells+1,1);
7364 int *cIPtr=cI->getPointer();
7368 for(it=a.begin();it!=a.end();it++)
7370 int curNbOfCell=(*it)->getNumberOfCells();
7371 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7372 const int *curC=(*it)->_nodal_connec->getConstPointer();
7373 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7374 for(int j=0;j<curNbOfCell;j++)
7376 const int *src=curC+curCI[j];
7378 for(;src!=curC+curCI[j+1];src++,cPtr++)
7386 offset+=curCI[curNbOfCell];
7387 offset2+=(*it)->getNumberOfNodes();
7390 ret->setConnectivity(c,cI,true);
7397 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7398 * dimension and sharing the node coordinates array.
7399 * All cells of the first mesh precede all cells of the second mesh
7400 * within the result mesh.
7401 * \param [in] mesh1 - the first mesh.
7402 * \param [in] mesh2 - the second mesh.
7403 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7404 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7405 * is no more needed.
7406 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7407 * \throw If the meshes do not share the node coordinates array.
7408 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7409 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7411 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7413 std::vector<const MEDCouplingUMesh *> tmp(2);
7414 tmp[0]=mesh1; tmp[1]=mesh2;
7415 return MergeUMeshesOnSameCoords(tmp);
7419 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7420 * dimension and sharing the node coordinates array.
7421 * All cells of the *i*-th mesh precede all cells of the
7422 * (*i*+1)-th mesh within the result mesh.
7423 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7424 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7425 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7426 * is no more needed.
7427 * \throw If \a a.size() == 0.
7428 * \throw If \a a[ *i* ] == NULL.
7429 * \throw If the meshes do not share the node coordinates array.
7430 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7431 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7433 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7436 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7437 for(std::size_t ii=0;ii<meshes.size();ii++)
7440 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7441 throw INTERP_KERNEL::Exception(oss.str().c_str());
7443 const DataArrayDouble *coords=meshes.front()->getCoords();
7444 int meshDim=meshes.front()->getMeshDimension();
7445 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7447 int meshIndexLgth=0;
7448 for(;iter!=meshes.end();iter++)
7450 if(coords!=(*iter)->getCoords())
7451 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7452 if(meshDim!=(*iter)->getMeshDimension())
7453 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7454 meshLgth+=(*iter)->getMeshLength();
7455 meshIndexLgth+=(*iter)->getNumberOfCells();
7457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7458 nodal->alloc(meshLgth,1);
7459 int *nodalPtr=nodal->getPointer();
7460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7461 nodalIndex->alloc(meshIndexLgth+1,1);
7462 int *nodalIndexPtr=nodalIndex->getPointer();
7464 for(iter=meshes.begin();iter!=meshes.end();iter++)
7466 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7467 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7468 int nbOfCells=(*iter)->getNumberOfCells();
7469 int meshLgth2=(*iter)->getMeshLength();
7470 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7471 if(iter!=meshes.begin())
7472 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7474 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7477 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7478 ret->setName("merge");
7479 ret->setMeshDimension(meshDim);
7480 ret->setConnectivity(nodal,nodalIndex,true);
7481 ret->setCoords(coords);
7486 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7487 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7488 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7489 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7490 * New" mode are returned for each input mesh.
7491 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7492 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7493 * valid values [0,1,2], see zipConnectivityTraducer().
7494 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7495 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7496 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7498 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7499 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7500 * is no more needed.
7501 * \throw If \a meshes.size() == 0.
7502 * \throw If \a meshes[ *i* ] == NULL.
7503 * \throw If the meshes do not share the node coordinates array.
7504 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7505 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7506 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7507 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7509 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7511 //All checks are delegated to MergeUMeshesOnSameCoords
7512 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7514 corr.resize(meshes.size());
7515 std::size_t nbOfMeshes=meshes.size();
7517 const int *o2nPtr=o2n->getConstPointer();
7518 for(std::size_t i=0;i<nbOfMeshes;i++)
7520 DataArrayInt *tmp=DataArrayInt::New();
7521 int curNbOfCells=meshes[i]->getNumberOfCells();
7522 tmp->alloc(curNbOfCells,1);
7523 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7524 offset+=curNbOfCells;
7525 tmp->setName(meshes[i]->getName());
7532 * Makes all given meshes share the nodal connectivity array. The common connectivity
7533 * array is created by concatenating the connectivity arrays of all given meshes. All
7534 * the given meshes must be of the same space dimension but dimension of cells **can
7535 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7536 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7537 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7538 * \param [in,out] meshes - a vector of meshes to update.
7539 * \throw If any of \a meshes is NULL.
7540 * \throw If the coordinates array is not set in any of \a meshes.
7541 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7542 * \throw If \a meshes are of different space dimension.
7544 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7546 std::size_t sz=meshes.size();
7549 std::vector< const DataArrayDouble * > coords(meshes.size());
7550 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7551 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7555 (*it)->checkConnectivityFullyDefined();
7556 const DataArrayDouble *coo=(*it)->getCoords();
7561 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7562 oss << " has no coordinate array defined !";
7563 throw INTERP_KERNEL::Exception(oss.str().c_str());
7568 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7569 oss << " is null !";
7570 throw INTERP_KERNEL::Exception(oss.str().c_str());
7573 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7574 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7575 int offset=(*it)->getNumberOfNodes();
7576 (*it++)->setCoords(res);
7577 for(;it!=meshes.end();it++)
7579 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7580 (*it)->setCoords(res);
7581 (*it)->shiftNodeNumbersInConn(offset);
7582 offset+=oldNumberOfNodes;
7587 * Merges nodes coincident with a given precision within all given meshes that share
7588 * the nodal connectivity array. The given meshes **can be of different** mesh
7589 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7590 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7591 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7592 * \param [in,out] meshes - a vector of meshes to update.
7593 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7594 * \throw If any of \a meshes is NULL.
7595 * \throw If the \a meshes do not share the same node coordinates array.
7596 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7598 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7602 std::set<const DataArrayDouble *> s;
7603 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7606 s.insert((*it)->getCoords());
7609 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 !";
7610 throw INTERP_KERNEL::Exception(oss.str().c_str());
7615 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 !";
7616 throw INTERP_KERNEL::Exception(oss.str().c_str());
7618 const DataArrayDouble *coo=*(s.begin());
7622 DataArrayInt *comm,*commI;
7623 coo->findCommonTuples(eps,-1,comm,commI);
7624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7625 int oldNbOfNodes=coo->getNumberOfTuples();
7627 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7628 if(oldNbOfNodes==newNbOfNodes)
7630 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7631 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7633 (*it)->renumberNodesInConn(o2n->getConstPointer());
7634 (*it)->setCoords(newCoords);
7639 * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [connBg,connEnd) and returns its extruded cell by inserting the result at the end of ret.
7640 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7641 * @param isQuad specifies the policy of connectivity.
7642 * @ret in/out parameter in which the result will be append
7644 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7646 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7647 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7648 ret.push_back(cm.getExtrudedType());
7649 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7652 case INTERP_KERNEL::NORM_POINT1:
7654 ret.push_back(connBg[1]);
7655 ret.push_back(connBg[1]+nbOfNodesPerLev);
7658 case INTERP_KERNEL::NORM_SEG2:
7660 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7661 ret.insert(ret.end(),conn,conn+4);
7664 case INTERP_KERNEL::NORM_SEG3:
7666 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7667 ret.insert(ret.end(),conn,conn+8);
7670 case INTERP_KERNEL::NORM_QUAD4:
7672 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7673 ret.insert(ret.end(),conn,conn+8);
7676 case INTERP_KERNEL::NORM_TRI3:
7678 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7679 ret.insert(ret.end(),conn,conn+6);
7682 case INTERP_KERNEL::NORM_TRI6:
7684 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,
7685 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7686 ret.insert(ret.end(),conn,conn+15);
7689 case INTERP_KERNEL::NORM_QUAD8:
7692 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7693 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7694 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7696 ret.insert(ret.end(),conn,conn+20);
7699 case INTERP_KERNEL::NORM_POLYGON:
7701 std::back_insert_iterator< std::vector<int> > ii(ret);
7702 std::copy(connBg+1,connEnd,ii);
7704 std::reverse_iterator<const int *> rConnBg(connEnd);
7705 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7706 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7707 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7708 for(std::size_t i=0;i<nbOfRadFaces;i++)
7711 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7712 std::copy(conn,conn+4,ii);
7717 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7722 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
7724 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7726 double v[3]={0.,0.,0.};
7727 std::size_t sz=std::distance(begin,end);
7730 for(std::size_t i=0;i<sz;i++)
7732 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];
7733 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7734 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7736 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7740 * The polyhedron is specfied by its connectivity nodes in [begin,end).
7742 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7744 std::vector<std::pair<int,int> > edges;
7745 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7746 const int *bgFace=begin;
7747 for(std::size_t i=0;i<nbOfFaces;i++)
7749 const int *endFace=std::find(bgFace+1,end,-1);
7750 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7751 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7753 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7754 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7756 edges.push_back(p1);
7760 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7764 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
7766 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7768 double vec0[3],vec1[3];
7769 std::size_t sz=std::distance(begin,end);
7771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7772 int nbOfNodes=(int)sz/2;
7773 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7774 const double *pt0=coords+3*begin[0];
7775 const double *pt1=coords+3*begin[nbOfNodes];
7776 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7777 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7780 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7782 std::size_t sz=std::distance(begin,end);
7783 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7784 std::size_t nbOfNodes(sz/2);
7785 std::copy(begin,end,(int *)tmp);
7786 for(std::size_t j=1;j<nbOfNodes;j++)
7788 begin[j]=tmp[nbOfNodes-j];
7789 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7793 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7795 std::size_t sz=std::distance(begin,end);
7797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7798 double vec0[3],vec1[3];
7799 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7800 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];
7801 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;
7804 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7806 std::size_t sz=std::distance(begin,end);
7808 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7810 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7811 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7812 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7816 * 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)
7817 * 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
7820 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7821 * \param [in] coords the coordinates with nb of components exactly equal to 3
7822 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7823 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7824 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7826 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7828 int nbFaces=std::count(begin+1,end,-1)+1;
7829 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7830 double *vPtr=v->getPointer();
7831 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7832 double *pPtr=p->getPointer();
7833 const int *stFaceConn=begin+1;
7834 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7836 const int *endFaceConn=std::find(stFaceConn,end,-1);
7837 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7838 stFaceConn=endFaceConn+1;
7840 pPtr=p->getPointer(); vPtr=v->getPointer();
7841 DataArrayInt *comm1=0,*commI1=0;
7842 v->findCommonTuples(eps,-1,comm1,commI1);
7843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7844 const int *comm1Ptr=comm1->getConstPointer();
7845 const int *commI1Ptr=commI1->getConstPointer();
7846 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7847 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7849 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7850 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7851 mm->finishInsertingCells();
7853 for(int i=0;i<nbOfGrps1;i++)
7855 int vecId=comm1Ptr[commI1Ptr[i]];
7856 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7857 DataArrayInt *comm2=0,*commI2=0;
7858 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7860 const int *comm2Ptr=comm2->getConstPointer();
7861 const int *commI2Ptr=commI2->getConstPointer();
7862 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7863 for(int j=0;j<nbOfGrps2;j++)
7865 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7867 res->insertAtTheEnd(begin,end);
7868 res->pushBackSilent(-1);
7872 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7874 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7875 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7876 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7877 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7880 const int *idsNodePtr=idsNode->getConstPointer();
7881 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];
7882 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7883 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7884 if(std::abs(norm)>eps)
7886 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7887 mm3->rotate(center,vec,angle);
7889 mm3->changeSpaceDimension(2);
7890 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7891 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7892 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7893 int nbOfCells=mm4->getNumberOfCells();
7894 for(int k=0;k<nbOfCells;k++)
7897 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7898 res->pushBackSilent(idsNodePtr[*work]);
7899 res->pushBackSilent(-1);
7904 res->popBackSilent();
7908 * 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
7909 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
7911 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7912 * \param [in] coords coordinates expected to have 3 components.
7913 * \param [in] begin start of the nodal connectivity of the face.
7914 * \param [in] end end of the nodal connectivity (excluded) of the face.
7915 * \param [out] v the normalized vector of size 3
7916 * \param [out] p the pos of plane
7918 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7920 std::size_t nbPoints=std::distance(begin,end);
7922 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7925 bool refFound=false;
7926 for(;j<nbPoints-1 && !refFound;j++)
7928 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7929 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7930 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7931 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7935 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7938 for(std::size_t i=j;i<nbPoints-1;i++)
7941 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7942 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7943 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7944 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7947 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7948 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];
7949 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7952 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7953 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7957 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7961 * This method tries to obtain a well oriented polyhedron.
7962 * If the algorithm fails, an exception will be thrown.
7964 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7966 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7967 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7968 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7970 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7971 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7972 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7974 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7977 std::size_t smthChanged=0;
7978 for(std::size_t i=0;i<nbOfFaces;i++)
7980 endFace=std::find(bgFace+1,end,-1);
7981 nbOfEdgesInFace=std::distance(bgFace,endFace);
7985 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7987 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7988 std::pair<int,int> p2(p1.second,p1.first);
7989 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7990 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7991 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7996 std::reverse(bgFace+1,endFace);
7997 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7999 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8000 std::pair<int,int> p2(p1.second,p1.first);
8001 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8002 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8003 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8004 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8005 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8006 if(it!=edgesOK.end())
8009 edgesFinished.push_back(p1);
8012 edgesOK.push_back(p1);
8019 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8021 if(!edgesOK.empty())
8022 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8023 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8024 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8026 for(std::size_t i=0;i<nbOfFaces;i++)
8028 endFace=std::find(bgFace+1,end,-1);
8029 std::reverse(bgFace+1,endFace);
8036 * This method makes the assumption spacedimension == meshdimension == 2.
8037 * This method works only for linear cells.
8039 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8041 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
8043 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8044 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8045 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8046 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8047 int nbOfNodesExpected=m->getNumberOfNodes();
8048 if(m->getNumberOfCells()!=nbOfNodesExpected)
8049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8051 const int *n2oPtr=n2o->getConstPointer();
8052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8053 m->getReverseNodalConnectivity(revNodal,revNodalI);
8054 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8055 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8056 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8058 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
8059 if(nbOfNodesExpected<1)
8062 int prevNode=nodalPtr[nodalIPtr[0]+1];
8063 *work++=n2oPtr[prevNode];
8064 for(int i=1;i<nbOfNodesExpected;i++)
8066 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8068 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8069 conn.erase(prevNode);
8072 int curNode=*(conn.begin());
8073 *work++=n2oPtr[curNode];
8074 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8075 shar.erase(prevCell);
8078 prevCell=*(shar.begin());
8082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8085 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8088 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8094 * This method makes the assumption spacedimension == meshdimension == 3.
8095 * This method works only for linear cells.
8097 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8099 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8101 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8102 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8103 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8104 const int *conn=m->getNodalConnectivity()->getConstPointer();
8105 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8106 int nbOfCells=m->getNumberOfCells();
8107 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8108 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8111 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8112 for(int i=1;i<nbOfCells;i++)
8115 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8121 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8122 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8124 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8128 for(int i=0;i<nbOfNodesInCell;i++)
8129 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8130 else if(spaceDim==2)
8132 for(int i=0;i<nbOfNodesInCell;i++)
8134 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8139 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8142 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8144 int nbOfCells=getNumberOfCells();
8146 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8147 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};
8148 ofs << " <" << getVTKDataSetType() << ">\n";
8149 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8150 ofs << " <PointData>\n" << pointData << std::endl;
8151 ofs << " </PointData>\n";
8152 ofs << " <CellData>\n" << cellData << std::endl;
8153 ofs << " </CellData>\n";
8154 ofs << " <Points>\n";
8155 if(getSpaceDimension()==3)
8156 _coords->writeVTK(ofs,8,"Points");
8159 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8160 coo->writeVTK(ofs,8,"Points");
8162 ofs << " </Points>\n";
8163 ofs << " <Cells>\n";
8164 const int *cPtr=_nodal_connec->getConstPointer();
8165 const int *cIPtr=_nodal_connec_index->getConstPointer();
8166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8167 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8170 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8171 int szFaceOffsets=0,szConn=0;
8172 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8175 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8178 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8179 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8183 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8184 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8185 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8186 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8187 w4=std::copy(c.begin(),c.end(),w4);
8190 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8191 types->writeVTK(ofs,8,"UInt8","types");
8192 offsets->writeVTK(ofs,8,"Int32","offsets");
8193 if(szFaceOffsets!=0)
8194 {//presence of Polyhedra
8195 connectivity->reAlloc(szConn);
8196 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8198 w1=faces->getPointer();
8199 for(int i=0;i<nbOfCells;i++)
8200 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8202 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8204 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8205 for(int j=0;j<nbFaces;j++)
8207 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8208 *w1++=(int)std::distance(w6,w5);
8209 w1=std::copy(w6,w5,w1);
8213 faces->writeVTK(ofs,8,"Int32","faces");
8215 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8216 ofs << " </Cells>\n";
8217 ofs << " </Piece>\n";
8218 ofs << " </" << getVTKDataSetType() << ">\n";
8221 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8223 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8225 { stream << " Not set !"; return ; }
8226 stream << " Mesh dimension : " << _mesh_dim << ".";
8230 { stream << " No coordinates set !"; return ; }
8231 if(!_coords->isAllocated())
8232 { stream << " Coordinates set but not allocated !"; return ; }
8233 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8234 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8235 if(!_nodal_connec_index)
8236 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8237 if(!_nodal_connec_index->isAllocated())
8238 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8239 int lgth=_nodal_connec_index->getNumberOfTuples();
8240 int cpt=_nodal_connec_index->getNumberOfComponents();
8241 if(cpt!=1 || lgth<1)
8243 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8246 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8248 return std::string("UnstructuredGrid");
8252 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8253 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8254 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8256 * \param [in] m1 - the first input mesh which is a partitioned object.
8257 * \param [in] m2 - the second input mesh which is a partition tool.
8258 * \param [in] eps - precision used to detect coincident mesh entities.
8259 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8260 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8261 * this array using decrRef() as it is no more needed.
8262 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8263 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8264 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8265 * any cell of \a m2. The caller is to delete this array using decrRef() as
8266 * it is no more needed.
8267 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8268 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8269 * is no more needed.
8270 * \throw If the coordinates array is not set in any of the meshes.
8271 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8272 * \throw If any of the meshes is not a 2D mesh in 2D space.
8274 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8276 m1->checkFullyDefined();
8277 m2->checkFullyDefined();
8278 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8280 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8281 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8282 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8283 std::vector<double> addCoo,addCoordsQuadratic;
8284 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8285 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8286 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8287 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8288 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8290 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8291 std::vector< std::vector<int> > intersectEdge2;
8292 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8293 subDiv2.clear(); dd5=0; dd6=0;
8294 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8295 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8296 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8297 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8299 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8300 addCooDa->alloc((int)(addCoo.size())/2,2);
8301 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8302 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8303 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8304 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8305 std::vector<const DataArrayDouble *> coordss(4);
8306 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8307 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8308 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8313 ret->setConnectivity(conn,connI,true);
8314 ret->setCoords(coo);
8315 cellNb1=c1.retn(); cellNb2=c2.retn();
8319 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8320 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8321 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8322 const std::vector<double>& addCoords,
8323 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8325 static const int SPACEDIM=2;
8326 std::vector<double> bbox1,bbox2;
8327 const double *coo1=m1->getCoords()->getConstPointer();
8328 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8329 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8330 int offset1=m1->getNumberOfNodes();
8331 const double *coo2=m2->getCoords()->getConstPointer();
8332 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8333 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8334 int offset2=offset1+m2->getNumberOfNodes();
8335 int offset3=offset2+((int)addCoords.size())/2;
8336 m1->getBoundingBoxForBBTree(bbox1);
8337 m2->getBoundingBoxForBBTree(bbox2);
8338 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8339 int ncell1=m1->getNumberOfCells();
8341 for(int i=0;i<ncell1;i++)
8343 std::vector<int> candidates2;
8344 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8345 std::map<INTERP_KERNEL::Node *,int> mapp;
8346 std::map<int,INTERP_KERNEL::Node *> mappRev;
8347 INTERP_KERNEL::QuadraticPolygon pol1;
8348 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8349 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8350 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8351 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8352 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8354 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
8355 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8356 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8357 for(it1.first();!it1.finished();it1.next())
8358 edges1.insert(it1.current()->getPtr());
8360 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8361 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8363 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8365 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8366 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8367 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8368 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8369 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8372 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8374 pol1.initLocationsWithOther(pol2s[ii]);
8375 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8376 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8377 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8383 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8385 catch(INTERP_KERNEL::Exception& e)
8387 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();
8388 throw INTERP_KERNEL::Exception(oss.str().c_str());
8391 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8392 (*it).second->decrRef();
8397 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8400 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8401 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8402 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8403 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8404 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8406 static const int SPACEDIM=2;
8407 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8408 desc2=DataArrayInt::New();
8409 descIndx2=DataArrayInt::New();
8410 revDesc2=DataArrayInt::New();
8411 revDescIndx2=DataArrayInt::New();
8412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8414 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8415 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8416 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8417 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8418 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8419 std::vector<double> bbox1,bbox2;
8420 m1Desc->getBoundingBoxForBBTree(bbox1);
8421 m2Desc->getBoundingBoxForBBTree(bbox2);
8422 int ncell1=m1Desc->getNumberOfCells();
8423 int ncell2=m2Desc->getNumberOfCells();
8424 intersectEdge1.resize(ncell1);
8425 colinear2.resize(ncell2);
8426 subDiv2.resize(ncell2);
8427 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8428 std::vector<int> candidates1(1);
8429 int offset1=m1->getNumberOfNodes();
8430 int offset2=offset1+m2->getNumberOfNodes();
8431 for(int i=0;i<ncell1;i++)
8433 std::vector<int> candidates2;
8434 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8435 if(!candidates2.empty())
8437 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8438 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8440 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8441 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8446 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8448 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8449 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8453 * This method performs the 2nd step of Partition of 2D mesh.
8454 * This method has 4 inputs :
8455 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8456 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8457 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8458 * 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'
8459 * @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'
8460 * @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.
8461 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8463 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)
8465 int offset1=m1->getNumberOfNodes();
8466 int ncell=m2->getNumberOfCells();
8467 const int *c=m2->getNodalConnectivity()->getConstPointer();
8468 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8469 const double *coo=m2->getCoords()->getConstPointer();
8470 const double *cooBis=m1->getCoords()->getConstPointer();
8471 int offset2=offset1+m2->getNumberOfNodes();
8472 intersectEdge.resize(ncell);
8473 for(int i=0;i<ncell;i++,cI++)
8475 const std::vector<int>& divs=subDiv[i];
8476 int nnode=cI[1]-cI[0]-1;
8477 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8478 std::map<INTERP_KERNEL::Node *, int> mapp22;
8479 for(int j=0;j<nnode;j++)
8481 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8482 int nnid=c[(*cI)+j+1];
8483 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8484 mapp22[nn]=nnid+offset1;
8486 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8487 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8488 ((*it).second.first)->decrRef();
8489 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8490 std::map<INTERP_KERNEL::Node *,int> mapp3;
8491 for(std::size_t j=0;j<divs.size();j++)
8494 INTERP_KERNEL::Node *tmp=0;
8496 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8498 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8500 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8504 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8505 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8512 * 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).
8513 * 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
8514 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8515 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8516 * @param nodesOnPlane, returns all the nodes that are on the plane.
8517 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
8518 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8519 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
8520 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8521 * @param desc is the descending connectivity 3DSurf->3DCurve
8522 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
8523 * @param cut3DSuf input/output param.
8525 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8526 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8527 const int *desc, const int *descIndx,
8528 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8530 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8531 int nbOf3DSurfCell=(int)cut3DSurf.size();
8532 for(int i=0;i<nbOf3DSurfCell;i++)
8534 std::vector<int> res;
8535 int offset=descIndx[i];
8536 int nbOfSeg=descIndx[i+1]-offset;
8537 for(int j=0;j<nbOfSeg;j++)
8539 int edgeId=desc[offset+j];
8540 int status=cut3DCurve[edgeId];
8544 res.push_back(status);
8547 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8548 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8556 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8562 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8563 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8566 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8570 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8575 {// case when plane is on a multi colinear edge of a polyhedron
8576 if((int)res.size()==2*nbOfSeg)
8578 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8581 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8588 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8589 * 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).
8590 * 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
8591 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8592 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8593 * @param desc is the descending connectivity 3D->3DSurf
8594 * @param descIndx is the descending connectivity index 3D->3DSurf
8596 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8597 const int *desc, const int *descIndx,
8598 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8600 checkFullyDefined();
8601 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8603 const int *nodal3D=_nodal_connec->getConstPointer();
8604 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8605 int nbOfCells=getNumberOfCells();
8606 for(int i=0;i<nbOfCells;i++)
8608 std::map<int, std::set<int> > m;
8609 int offset=descIndx[i];
8610 int nbOfFaces=descIndx[i+1]-offset;
8613 for(int j=0;j<nbOfFaces;j++)
8615 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8616 if(p.first!=-1 && p.second!=-1)
8620 start=p.first; end=p.second;
8621 m[p.first].insert(p.second);
8622 m[p.second].insert(p.first);
8626 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8627 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8628 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8629 INTERP_KERNEL::NormalizedCellType cmsId;
8630 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8631 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8632 for(unsigned k=0;k<nbOfNodesSon;k++)
8634 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8635 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8642 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8646 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8647 const std::set<int>& s=(*it).second;
8648 std::set<int> s2; s2.insert(prev);
8650 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8653 int val=*s3.begin();
8654 conn.push_back(start);
8661 conn.push_back(end);
8664 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8665 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8666 cellIds->pushBackSilent(i);
8672 * 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
8673 * 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
8674 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8675 * 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
8676 * 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.
8678 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8680 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8682 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8685 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8686 if(cm.getDimension()==2)
8688 const int *node=nodalConnBg+1;
8689 int startNode=*node++;
8690 double refX=coords[2*startNode];
8691 for(;node!=nodalConnEnd;node++)
8693 if(coords[2*(*node)]<refX)
8696 refX=coords[2*startNode];
8699 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8703 double angle0=-M_PI/2;
8709 while(nextNode!=startNode)
8713 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8715 if(*node!=tmpOut.back() && *node!=prevNode)
8717 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8718 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8723 res=angle0-angleM+2.*M_PI;
8732 if(nextNode!=startNode)
8734 angle0=angleNext-M_PI;
8737 prevNode=tmpOut.back();
8738 tmpOut.push_back(nextNode);
8741 std::vector<int> tmp3(2*(sz-1));
8742 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8743 std::copy(nodalConnBg+1,nodalConnEnd,it);
8744 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8746 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8749 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8751 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8756 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8757 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8762 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8765 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8769 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8770 * 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.
8772 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8773 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8774 * \param [in,out] arr array in which the remove operation will be done.
8775 * \param [in,out] arrIndx array in the remove operation will modify
8776 * \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])
8777 * \return true if \b arr and \b arrIndx have been modified, false if not.
8779 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8781 if(!arrIndx || !arr)
8782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8783 if(offsetForRemoval<0)
8784 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8785 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8786 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8787 int *arrIPtr=arrIndx->getPointer();
8790 const int *arrPtr=arr->getConstPointer();
8791 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8792 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8794 if(*arrIPtr-previousArrI>offsetForRemoval)
8796 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8798 if(s.find(*work)==s.end())
8799 arrOut.push_back(*work);
8802 previousArrI=*arrIPtr;
8803 *arrIPtr=(int)arrOut.size();
8805 if(arr->getNumberOfTuples()==(int)arrOut.size())
8807 arr->alloc((int)arrOut.size(),1);
8808 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8813 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8814 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8815 * The selection of extraction is done standardly in new2old format.
8816 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8818 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8819 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8820 * \param [in] arrIn arr origin array from which the extraction will be done.
8821 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8822 * \param [out] arrOut the resulting array
8823 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8825 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8826 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8828 if(!arrIn || !arrIndxIn)
8829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8830 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8831 const int *arrInPtr=arrIn->getConstPointer();
8832 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8833 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8834 int maxSizeOfArr=arrIn->getNumberOfTuples();
8835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8837 arrIo->alloc((int)(sz+1),1);
8838 const int *idsIt=idsOfSelectBg;
8839 int *work=arrIo->getPointer();
8842 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8844 if(*idsIt>=0 && *idsIt<nbOfGrps)
8845 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8848 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8849 throw INTERP_KERNEL::Exception(oss.str().c_str());
8855 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8856 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8857 throw INTERP_KERNEL::Exception(oss.str().c_str());
8860 arro->alloc(lgth,1);
8861 work=arro->getPointer();
8862 idsIt=idsOfSelectBg;
8863 for(std::size_t i=0;i<sz;i++,idsIt++)
8865 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8866 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8869 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8870 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8871 throw INTERP_KERNEL::Exception(oss.str().c_str());
8875 arrIndexOut=arrIo.retn();
8879 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8880 * 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
8881 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8882 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8884 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8885 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8886 * \param [in] arrIn arr origin array from which the extraction will be done.
8887 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8888 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8889 * \param [in] srcArrIndex index array of \b srcArr
8890 * \param [out] arrOut the resulting array
8891 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8893 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8895 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8896 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8897 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8899 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8900 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8903 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8904 std::vector<bool> v(nbOfTuples,true);
8906 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8907 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8908 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8910 if(*it>=0 && *it<nbOfTuples)
8913 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8917 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8918 throw INTERP_KERNEL::Exception(oss.str().c_str());
8921 srcArrIndexPtr=srcArrIndex->getConstPointer();
8922 arrIo->alloc(nbOfTuples+1,1);
8923 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8924 const int *arrInPtr=arrIn->getConstPointer();
8925 const int *srcArrPtr=srcArr->getConstPointer();
8926 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8927 int *arroPtr=arro->getPointer();
8928 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8932 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8933 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8937 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8938 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8939 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8943 arrIndexOut=arrIo.retn();
8947 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8948 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8950 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8951 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8952 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8953 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8954 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8955 * \param [in] srcArrIndex index array of \b srcArr
8957 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8959 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8960 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8962 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8963 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8964 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8965 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8966 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8967 int *arrInOutPtr=arrInOut->getPointer();
8968 const int *srcArrPtr=srcArr->getConstPointer();
8969 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8971 if(*it>=0 && *it<nbOfTuples)
8973 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8974 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8977 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] !";
8978 throw INTERP_KERNEL::Exception(oss.str().c_str());
8983 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8984 throw INTERP_KERNEL::Exception(oss.str().c_str());
8990 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8991 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8992 * 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]].
8993 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8994 * A negative value in \b arrIn means that it is ignored.
8995 * 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.
8997 * \param [in] arrIn arr origin array from which the extraction will be done.
8998 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8999 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9000 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9002 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9004 int seed=0,nbOfDepthPeelingPerformed=0;
9005 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9009 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9010 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9011 * 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]].
9012 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9013 * A negative value in \b arrIn means that it is ignored.
9014 * 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.
9015 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9016 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9017 * \param [in] arrIn arr origin array from which the extraction will be done.
9018 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9019 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9020 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9021 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9022 * \sa MEDCouplingUMesh::partitionBySpreadZone
9024 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9026 nbOfDepthPeelingPerformed=0;
9028 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9029 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9032 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9036 std::vector<bool> fetched(nbOfTuples,false);
9037 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9040 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)
9042 nbOfDepthPeelingPerformed=0;
9043 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9044 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9045 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9046 std::vector<bool> fetched2(nbOfTuples,false);
9048 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9050 if(*seedElt>=0 && *seedElt<nbOfTuples)
9051 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9053 { 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()); }
9055 const int *arrInPtr=arrIn->getConstPointer();
9056 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9057 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9058 std::vector<int> idsToFetch1(seedBg,seedEnd);
9059 std::vector<int> idsToFetch2;
9060 std::vector<int> *idsToFetch=&idsToFetch1;
9061 std::vector<int> *idsToFetchOther=&idsToFetch2;
9062 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9064 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9065 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9067 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9068 std::swap(idsToFetch,idsToFetchOther);
9069 idsToFetchOther->clear();
9070 nbOfDepthPeelingPerformed++;
9072 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9075 int *retPtr=ret->getPointer();
9076 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9083 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9084 * 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
9085 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9086 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9088 * \param [in] start begin of set of ids of the input extraction (included)
9089 * \param [in] end end of set of ids of the input extraction (excluded)
9090 * \param [in] step step of the set of ids in range mode.
9091 * \param [in] arrIn arr origin array from which the extraction will be done.
9092 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9093 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9094 * \param [in] srcArrIndex index array of \b srcArr
9095 * \param [out] arrOut the resulting array
9096 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9098 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9100 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9101 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9102 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9104 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9105 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9107 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9108 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9110 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9111 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9112 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9114 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9116 if(it>=0 && it<nbOfTuples)
9117 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9120 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9121 throw INTERP_KERNEL::Exception(oss.str().c_str());
9124 srcArrIndexPtr=srcArrIndex->getConstPointer();
9125 arrIo->alloc(nbOfTuples+1,1);
9126 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9127 const int *arrInPtr=arrIn->getConstPointer();
9128 const int *srcArrPtr=srcArr->getConstPointer();
9129 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9130 int *arroPtr=arro->getPointer();
9131 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9133 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9136 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9137 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9141 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9142 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9146 arrIndexOut=arrIo.retn();
9150 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9151 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9153 * \param [in] start begin of set of ids of the input extraction (included)
9154 * \param [in] end end of set of ids of the input extraction (excluded)
9155 * \param [in] step step of the set of ids in range mode.
9156 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9157 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9158 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9159 * \param [in] srcArrIndex index array of \b srcArr
9161 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9163 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9164 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9166 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9167 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9168 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9169 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9170 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9171 int *arrInOutPtr=arrInOut->getPointer();
9172 const int *srcArrPtr=srcArr->getConstPointer();
9173 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9175 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9177 if(it>=0 && it<nbOfTuples)
9179 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9180 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9183 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9184 throw INTERP_KERNEL::Exception(oss.str().c_str());
9189 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9190 throw INTERP_KERNEL::Exception(oss.str().c_str());
9196 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9197 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9198 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9199 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9200 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9202 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9204 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9206 checkFullyDefined();
9207 int mdim=getMeshDimension();
9208 int spaceDim=getSpaceDimension();
9210 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9211 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9212 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9213 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9214 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9215 ret->setCoords(getCoords());
9216 ret->allocateCells((int)partition.size());
9218 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9220 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9225 cell=tmp->buildUnionOf2DMesh();
9228 cell=tmp->buildUnionOf3DMesh();
9231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9234 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9237 ret->finishInsertingCells();
9242 * This method partitions \b this into contiguous zone.
9243 * This method only needs a well defined connectivity. Coordinates are not considered here.
9244 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9246 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9249 int nbOfCellsCur=getNumberOfCells();
9250 std::vector<DataArrayInt *> ret;
9253 DataArrayInt *neigh=0,*neighI=0;
9254 computeNeighborsOfCells(neigh,neighI);
9255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9256 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9257 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9259 while(seed<nbOfCellsCur)
9261 int nbOfPeelPerformed=0;
9262 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9263 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9265 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9266 ret.push_back((*it).retn());
9270 int nbOfCellsCur=getNumberOfCells();
9271 DataArrayInt *neigh=0,*neighI=0;
9272 computeNeighborsOfCells(neigh,neighI);
9273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9275 std::vector<DataArrayInt *> ret;
9276 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9277 while(nbOfCellsCur>0)
9279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9282 ret2.push_back(tmp2); ret.push_back(tmp2);
9283 nbOfCellsCur=tmp3->getNumberOfTuples();
9286 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9287 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9291 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9294 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9301 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9302 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9304 * \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.
9305 * \return a newly allocated DataArrayInt to be managed by the caller.
9306 * \throw In case of \a code has not the right format (typically of size 3*n)
9308 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9311 std::size_t nb=code.size()/3;
9312 if(code.size()%3!=0)
9313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9314 ret->alloc((int)nb,2);
9315 int *retPtr=ret->getPointer();
9316 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9318 retPtr[0]=code[3*i+2];
9319 retPtr[1]=code[3*i+2]+code[3*i+1];
9324 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9325 _own_cell(true),_cell_id(-1),_nb_cell(0)
9330 _nb_cell=mesh->getNumberOfCells();
9334 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9342 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9343 _own_cell(false),_cell_id(bg-1),
9350 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9353 if(_cell_id<_nb_cell)
9362 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9368 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9370 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9373 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9379 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9387 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9393 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9398 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9403 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9405 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9408 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9413 _nb_cell=mesh->getNumberOfCells();
9417 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9424 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9426 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9427 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9428 if(_cell_id<_nb_cell)
9430 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9431 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9432 int startId=_cell_id;
9433 _cell_id+=nbOfElems;
9434 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9440 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9444 _conn=mesh->getNodalConnectivity()->getPointer();
9445 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9449 void MEDCouplingUMeshCell::next()
9451 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9456 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9459 std::string MEDCouplingUMeshCell::repr() const
9461 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9463 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9465 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9469 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9472 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9474 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9475 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9477 return INTERP_KERNEL::NORM_ERROR;
9480 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9483 if(_conn_lgth!=NOTICABLE_FIRST_VAL)