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 "BBTreeDst.txx"
30 #include "SplitterTetra.hxx"
31 #include "DirectedBoundingBox.hxx"
32 #include "InterpKernelMeshQuality.hxx"
33 #include "InterpKernelCellSimplify.hxx"
34 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
35 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
36 #include "InterpKernelAutoPtr.hxx"
37 #include "InterpKernelGeo2DNode.hxx"
38 #include "InterpKernelGeo2DEdgeLin.hxx"
39 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
40 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
49 using namespace ParaMEDMEM;
51 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53 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 };
55 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 return new MEDCouplingUMesh;
60 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
63 ret->setName(meshName);
64 ret->setMeshDimension(meshDim);
69 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
70 * between \a this and the new mesh.
71 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
72 * delete this mesh using decrRef() as it is no more needed.
74 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
80 * Returns a new MEDCouplingMesh which is a copy of \a this one.
81 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
82 * this mesh are shared by the new mesh.
83 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
84 * delete this mesh using decrRef() as it is no more needed.
86 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 return new MEDCouplingUMesh(*this,recDeepCpy);
91 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
95 ret+=_nodal_connec->getHeapMemorySize();
96 if(_nodal_connec_index)
97 ret+=_nodal_connec_index->getHeapMemorySize();
98 return MEDCouplingPointSet::getHeapMemorySize()+ret;
101 void MEDCouplingUMesh::updateTime() const
103 MEDCouplingPointSet::updateTime();
106 updateTimeWith(*_nodal_connec);
108 if(_nodal_connec_index)
110 updateTimeWith(*_nodal_connec_index);
114 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
119 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
120 * then \a this mesh is most probably is writable, exchangeable and available for most
121 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
122 * this method to check that all is in order with \a this mesh.
123 * \throw If the mesh dimension is not set.
124 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
125 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
126 * \throw If the connectivity data array has more than one component.
127 * \throw If the connectivity data array has a named component.
128 * \throw If the connectivity index data array has more than one component.
129 * \throw If the connectivity index data array has a named component.
131 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
134 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
136 MEDCouplingPointSet::checkCoherency();
137 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
139 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
141 std::ostringstream message;
142 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
143 throw INTERP_KERNEL::Exception(message.str().c_str());
148 if(_nodal_connec->getNumberOfComponents()!=1)
149 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
150 if(_nodal_connec->getInfoOnComponent(0)!="")
151 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
153 if(_nodal_connec_index)
155 if(_nodal_connec_index->getNumberOfComponents()!=1)
156 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
157 if(_nodal_connec_index->getInfoOnComponent(0)!="")
158 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
163 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
164 * then \a this mesh is most probably is writable, exchangeable and available for all
165 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
166 * method thoroughly checks the nodal connectivity.
167 * \param [in] eps - a not used parameter.
168 * \throw If the mesh dimension is not set.
169 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
170 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
171 * \throw If the connectivity data array has more than one component.
172 * \throw If the connectivity data array has a named component.
173 * \throw If the connectivity index data array has more than one component.
174 * \throw If the connectivity index data array has a named component.
175 * \throw If number of nodes defining an element does not correspond to the type of element.
176 * \throw If the nodal connectivity includes an invalid node id.
178 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
183 int meshDim=getMeshDimension();
184 int nbOfNodes=getNumberOfNodes();
185 int nbOfCells=getNumberOfCells();
186 const int *ptr=_nodal_connec->getConstPointer();
187 const int *ptrI=_nodal_connec_index->getConstPointer();
188 for(int i=0;i<nbOfCells;i++)
190 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
191 if((int)cm.getDimension()!=meshDim)
193 std::ostringstream oss;
194 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
195 throw INTERP_KERNEL::Exception(oss.str().c_str());
197 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
199 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
201 std::ostringstream oss;
202 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
203 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
204 throw INTERP_KERNEL::Exception(oss.str().c_str());
206 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
211 if(nodeId>=nbOfNodes)
213 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
214 throw INTERP_KERNEL::Exception(oss.str().c_str());
219 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
220 throw INTERP_KERNEL::Exception(oss.str().c_str());
224 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
226 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
227 throw INTERP_KERNEL::Exception(oss.str().c_str());
236 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
237 * then \a this mesh is most probably is writable, exchangeable and available for all
238 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
239 * \param [in] eps - a not used parameter.
240 * \throw If the mesh dimension is not set.
241 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
242 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
243 * \throw If the connectivity data array has more than one component.
244 * \throw If the connectivity data array has a named component.
245 * \throw If the connectivity index data array has more than one component.
246 * \throw If the connectivity index data array has a named component.
247 * \throw If number of nodes defining an element does not correspond to the type of element.
248 * \throw If the nodal connectivity includes an invalid node id.
250 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
252 checkCoherency1(eps);
256 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
257 * elements contained in the mesh. For more info on the mesh dimension see
258 * \ref MEDCouplingUMeshPage.
259 * \param [in] meshDim - a new mesh dimension.
260 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
262 void MEDCouplingUMesh::setMeshDimension(int meshDim)
264 if(meshDim<-1 || meshDim>3)
265 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
271 * Allocates memory to store given number of cells.
272 * \param [in] nbOfCells - number of cell \a this mesh will contain.
274 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
275 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
277 void MEDCouplingUMesh::allocateCells(int nbOfCells)
279 if(_nodal_connec_index)
281 _nodal_connec_index->decrRef();
285 _nodal_connec->decrRef();
287 _nodal_connec_index=DataArrayInt::New();
288 _nodal_connec_index->reserve(nbOfCells+1);
289 _nodal_connec_index->pushBackSilent(0);
290 _nodal_connec=DataArrayInt::New();
291 _nodal_connec->reserve(2*nbOfCells);
297 * Appends a cell to the connectivity array. For deeper understanding what is
298 * happening see \ref MEDCouplingUMeshNodalConnectivity.
299 * \param [in] type - type of cell to add.
300 * \param [in] size - number of nodes constituting this cell.
301 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
303 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
304 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
306 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
308 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
309 if(_nodal_connec_index==0)
310 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
311 if((int)cm.getDimension()==_mesh_dim)
314 if(size!=(int)cm.getNumberOfNodes())
316 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
317 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
318 throw INTERP_KERNEL::Exception(oss.str().c_str());
320 int idx=_nodal_connec_index->back();
322 _nodal_connec_index->pushBackSilent(val);
323 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
328 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
329 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
330 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
331 throw INTERP_KERNEL::Exception(oss.str().c_str());
336 * Compacts data arrays to release unused memory. This method is to be called after
337 * finishing cell insertion using \a this->insertNextCell().
339 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
340 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
342 void MEDCouplingUMesh::finishInsertingCells()
344 _nodal_connec->pack();
345 _nodal_connec_index->pack();
346 _nodal_connec->declareAsNew();
347 _nodal_connec_index->declareAsNew();
352 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
353 * Useful for python users.
355 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
357 return new MEDCouplingUMeshCellIterator(this);
361 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
362 * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
363 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
364 * Useful for python users.
366 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
368 if(!checkConsecutiveCellTypes())
369 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
370 return new MEDCouplingUMeshCellByTypeEntry(this);
374 * Returns a set of all cell types available in \a this mesh.
375 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
377 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
383 * This method is a method that compares 'this' and 'other'.
384 * This method compares \b all attributes, even names and component names.
386 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
389 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
390 std::ostringstream oss; oss.precision(15);
391 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
394 reason="mesh given in input is not castable in MEDCouplingUMesh !";
397 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
399 if(_mesh_dim!=otherC->_mesh_dim)
401 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
405 if(_types!=otherC->_types)
407 oss << "umesh geometric type mismatch :\nThis geometric types are :";
408 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
409 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
410 oss << "\nOther geometric types are :";
411 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
412 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
416 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
417 if(_nodal_connec==0 || otherC->_nodal_connec==0)
419 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
422 if(_nodal_connec!=otherC->_nodal_connec)
423 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
425 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
428 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
429 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
431 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
434 if(_nodal_connec_index!=otherC->_nodal_connec_index)
435 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
437 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
444 * Checks if data arrays of this mesh (node coordinates, nodal
445 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
447 * \param [in] other - the mesh to compare with.
448 * \param [in] prec - precision value used to compare node coordinates.
449 * \return bool - \a true if the two meshes are same.
451 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
453 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
456 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
458 if(_mesh_dim!=otherC->_mesh_dim)
460 if(_types!=otherC->_types)
462 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
463 if(_nodal_connec==0 || otherC->_nodal_connec==0)
465 if(_nodal_connec!=otherC->_nodal_connec)
466 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
468 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
469 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
471 if(_nodal_connec_index!=otherC->_nodal_connec_index)
472 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
478 * Checks if \a this and \a other meshes are geometrically equivalent, else an
479 * exception is thrown. The meshes are
480 * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
481 * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
482 * the \a other mesh (with use of a specified cell comparison technique). The mapping
483 * from \a other to \a this for nodes and cells is returned via out parameters.
484 * \param [in] other - the mesh to compare with.
485 * \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
486 * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
487 * \param [in] prec - the precision used to compare nodes of the two meshes.
488 * \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
489 * to delete this array using decrRef() as it is no more needed.
490 * \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
491 * to delete this array using decrRef() as it is no more needed.
492 * \throw If the two meshes do not match.
494 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
495 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
497 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
498 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
500 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
502 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
503 MEDCouplingMesh::checkFastEquivalWith(other,prec);
504 if(_types!=otherC->_types)
505 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
506 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
509 int oldNbOfNodes=getNumberOfNodes();
510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
513 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
514 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
515 if(pt!=da->getConstPointer()+da->getNbOfElems())
516 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
517 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
519 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
520 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
523 da=m->zipConnectivityTraducer(cellCompPol);
524 int nbCells=getNumberOfCells();
527 maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
528 pt=std::find_if(da->getConstPointer()+nbCells,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
529 if(pt!=da->getConstPointer()+da->getNbOfElems())
530 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
531 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(nbCells,da->getNbOfElems(),1);
532 nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
533 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
537 * Checks if \a this and \a other meshes are geometrically equivalent, else an
538 * exception is thrown. The meshes are considered equivalent if (1) they share one
539 * node coordinates array and (2) they contain the same cells (with use of a specified
540 * cell comparison technique). The mapping from cells of the \a other to ones of \a this
541 * is returned via an out parameter.
542 * \param [in] other - the mesh to compare with.
543 * \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
544 * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
545 * \param [in] prec - a not used parameter.
546 * \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
547 * to delete this array using decrRef() as it is no more needed.
548 * \throw If the two meshes do not match.
550 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
551 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
553 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
554 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
556 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
558 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
559 MEDCouplingMesh::checkFastEquivalWith(other,prec);
560 if(_types!=otherC->_types)
561 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
562 if(_coords!=otherC->_coords)
563 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
564 std::vector<const MEDCouplingUMesh *> ms(2);
567 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
568 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
569 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
570 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
571 if(pt!=da->getConstPointer()+da->getNbOfElems())
573 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
576 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
580 * Checks if \a this and \a other meshes are geometrically equivalent with high
581 * probability, else an exception is thrown. The meshes are considered equivalent if
582 * (1) meshes contain the same number of nodes and the same number of elements of the
583 * same types (2) three cells of the two meshes (first, last and middle) are based
584 * on coincident nodes (with a specified precision).
585 * \param [in] other - the mesh to compare with.
586 * \param [in] prec - the precision used to compare nodes of the two meshes.
587 * \throw If the two meshes do not match.
589 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
591 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
593 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
594 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
595 int nbOfCells=getNumberOfCells();
599 status&=areCellsFrom2MeshEqual(otherC,0,prec);
600 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
601 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
603 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
607 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
608 * cells each node belongs to.
609 * \warning For speed reasons, this method does not check if node ids in the nodal
610 * connectivity correspond to the size of node coordinates array.
611 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
612 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
613 * dividing cell ids in \a revNodal into groups each referring to one
614 * node. Its every element (except the last one) is an index pointing to the
615 * first id of a group of cells. For example cells sharing the node #1 are
616 * described by following range of indices:
617 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
618 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
619 * Number of cells sharing the *i*-th node is
620 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
621 * \throw If the coordinates array is not set.
622 * \throw If the nodal connectivity of cells is not defined.
624 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
625 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
627 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
630 int nbOfNodes=getNumberOfNodes();
631 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
632 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
633 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
634 const int *conn=_nodal_connec->getConstPointer();
635 const int *connIndex=_nodal_connec_index->getConstPointer();
636 int nbOfCells=getNumberOfCells();
637 int nbOfEltsInRevNodal=0;
638 for(int eltId=0;eltId<nbOfCells;eltId++)
640 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
641 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
642 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
643 if(*iter>=0)//for polyhedrons
645 nbOfEltsInRevNodal++;
646 revNodalIndxPtr[(*iter)+1]++;
649 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
650 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
651 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
652 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
653 for(int eltId=0;eltId<nbOfCells;eltId++)
655 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
656 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
657 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
658 if(*iter>=0)//for polyhedrons
659 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
665 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
670 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
676 if(cm.getOrientationStatus(nb,conn1,conn2))
683 class MinusOneSonsGenerator
686 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
688 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689 static const int DELTA=1;
691 const INTERP_KERNEL::CellModel& _cm;
694 class MinusOneSonsGeneratorBiQuadratic
697 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
698 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
699 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
700 static const int DELTA=1;
702 const INTERP_KERNEL::CellModel& _cm;
705 class MinusTwoSonsGenerator
708 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
709 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
710 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
711 static const int DELTA=2;
713 const INTERP_KERNEL::CellModel& _cm;
719 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
720 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
721 * describing correspondence between cells of \a this and the result meshes are
722 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
723 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
724 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
725 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
726 * \warning For speed reasons, this method does not check if node ids in the nodal
727 * connectivity correspond to the size of node coordinates array.
728 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
729 * to write this mesh to the MED file, its cells must be sorted using
730 * sortCellsInMEDFileFrmt().
731 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
732 * each cell of \a this mesh.
733 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
734 * dividing cell ids in \a desc into groups each referring to one
735 * cell of \a this mesh. Its every element (except the last one) is an index
736 * pointing to the first id of a group of cells. For example cells of the
737 * result mesh bounding the cell #1 of \a this mesh are described by following
739 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
740 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
741 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
742 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
743 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
744 * by each cell of the result mesh.
745 * \param [in,out] revDescIndx - the array, of length one more than number of cells
746 * in the result mesh,
747 * dividing cell ids in \a revDesc into groups each referring to one
748 * cell of the result mesh the same way as \a descIndx divides \a desc.
749 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
750 * delete this mesh using decrRef() as it is no more needed.
751 * \throw If the coordinates array is not set.
752 * \throw If the nodal connectivity of cells is node defined.
753 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
754 * revDescIndx == NULL.
756 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
757 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
758 * \sa buildDescendingConnectivity2()
760 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
762 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
766 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
767 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
768 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
769 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
770 * \sa MEDCouplingUMesh::buildDescendingConnectivity
772 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
775 if(getMeshDimension()!=3)
776 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
777 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
781 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
782 * this->getMeshDimension(), that bound cells of \a this mesh. In
783 * addition arrays describing correspondence between cells of \a this and the result
784 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
785 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
786 * mesh. This method differs from buildDescendingConnectivity() in that apart
787 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
788 * result meshes. So a positive id means that order of nodes in corresponding cells
789 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
790 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
791 * i.e. cell ids are one-based.
792 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
793 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
794 * \warning For speed reasons, this method does not check if node ids in the nodal
795 * connectivity correspond to the size of node coordinates array.
796 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
797 * to write this mesh to the MED file, its cells must be sorted using
798 * sortCellsInMEDFileFrmt().
799 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
800 * each cell of \a this mesh.
801 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
802 * dividing cell ids in \a desc into groups each referring to one
803 * cell of \a this mesh. Its every element (except the last one) is an index
804 * pointing to the first id of a group of cells. For example cells of the
805 * result mesh bounding the cell #1 of \a this mesh are described by following
807 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
808 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
809 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
810 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
811 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
812 * by each cell of the result mesh.
813 * \param [in,out] revDescIndx - the array, of length one more than number of cells
814 * in the result mesh,
815 * dividing cell ids in \a revDesc into groups each referring to one
816 * cell of the result mesh the same way as \a descIndx divides \a desc.
817 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
818 * shares the node coordinates array with \a this mesh. The caller is to
819 * delete this mesh using decrRef() as it is no more needed.
820 * \throw If the coordinates array is not set.
821 * \throw If the nodal connectivity of cells is node defined.
822 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
823 * revDescIndx == NULL.
825 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
826 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
827 * \sa buildDescendingConnectivity()
829 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
831 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
835 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
836 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
837 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
838 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
840 * \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
841 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
842 * \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.
844 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
850 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
852 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
856 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
857 * 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,
858 * excluding a set of meshdim-1 cells in input descending connectivity.
859 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
860 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
861 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
863 * \param [in] desc descending connectivity array.
864 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
865 * \param [in] revDesc reverse descending connectivity array.
866 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
867 * \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
868 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
869 * \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.
871 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
872 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
874 if(!desc || !descIndx || !revDesc || !revDescIndx)
875 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
876 const int *descPtr=desc->getConstPointer();
877 const int *descIPtr=descIndx->getConstPointer();
878 const int *revDescPtr=revDesc->getConstPointer();
879 const int *revDescIPtr=revDescIndx->getConstPointer();
881 int nbCells=descIndx->getNumberOfTuples()-1;
882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
884 int *out1Ptr=out1->getPointer();
886 out0->reserve(desc->getNumberOfTuples());
887 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
889 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
891 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
893 out0->insertAtTheEnd(s.begin(),s.end());
895 *out1Ptr=out0->getNumberOfTuples();
897 neighbors=out0.retn();
898 neighborsIndx=out1.retn();
904 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
905 * For speed reasons no check of this will be done.
907 template<class SonsGenerator>
908 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
910 if(!desc || !descIndx || !revDesc || !revDescIndx)
911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
912 checkConnectivityFullyDefined();
913 int nbOfCells=getNumberOfCells();
914 int nbOfNodes=getNumberOfNodes();
915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
916 int *revNodalIndxPtr=revNodalIndx->getPointer();
917 const int *conn=_nodal_connec->getConstPointer();
918 const int *connIndex=_nodal_connec_index->getConstPointer();
919 std::string name="Mesh constituent of "; name+=getName();
920 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
921 ret->setCoords(getCoords());
922 ret->allocateCells(2*nbOfCells);
923 descIndx->alloc(nbOfCells+1,1);
924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
925 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
926 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
928 int pos=connIndex[eltId];
929 int posP1=connIndex[eltId+1];
930 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
931 SonsGenerator sg(cm);
932 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
933 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
934 for(unsigned i=0;i<nbOfSons;i++)
936 INTERP_KERNEL::NormalizedCellType cmsId;
937 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
938 for(unsigned k=0;k<nbOfNodesSon;k++)
940 revNodalIndxPtr[tmp[k]+1]++;
941 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
942 revDesc2->pushBackSilent(eltId);
944 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
946 int nbOfCellsM1=ret->getNumberOfCells();
947 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
949 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
950 int *revNodalPtr=revNodal->getPointer();
951 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
952 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
953 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
955 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
956 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
957 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
958 if(*iter>=0)//for polyhedrons
959 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
962 DataArrayInt *commonCells=0,*commonCellsI=0;
963 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
965 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
966 int newNbOfCellsM1=-1;
967 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
968 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
969 std::vector<bool> isImpacted(nbOfCellsM1,false);
970 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
971 for(int work2=work[0];work2!=work[1];work2++)
972 isImpacted[commonCellsPtr[work2]]=true;
973 const int *o2nM1Ptr=o2nM1->getConstPointer();
974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
975 const int *n2oM1Ptr=n2oM1->getConstPointer();
976 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
977 ret2->copyTinyInfoFrom(this);
978 desc->alloc(descIndx->back(),1);
979 int *descPtr=desc->getPointer();
980 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
981 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
984 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
987 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
989 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
990 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
993 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
996 revDesc->reserve(newNbOfCellsM1);
997 revDescIndx->alloc(newNbOfCellsM1+1,1);
998 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
999 const int *revDesc2Ptr=revDesc2->getConstPointer();
1000 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1002 int oldCellIdM1=n2oM1Ptr[i];
1003 if(!isImpacted[oldCellIdM1])
1005 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1006 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1010 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1011 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1012 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1020 struct MEDCouplingAccVisit
1022 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1023 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1024 int _new_nb_of_nodes;
1030 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1031 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1032 * array of cell ids. Pay attention that after conversion all algorithms work slower
1033 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1034 * conversion due presence of invalid ids in the array of cells to convert, as a
1035 * result \a this mesh contains some already converted elements. In this case the 2D
1036 * mesh remains valid but 3D mesh becomes \b inconsistent!
1037 * \warning This method can significantly modify the order of geometric types in \a this,
1038 * hence, to write this mesh to the MED file, its cells must be sorted using
1039 * sortCellsInMEDFileFrmt().
1040 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1041 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1042 * cellIdsToConvertBg.
1043 * \throw If the coordinates array is not set.
1044 * \throw If the nodal connectivity of cells is node defined.
1045 * \throw If dimension of \a this mesh is not either 2 or 3.
1047 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1048 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1050 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1052 checkFullyDefined();
1053 int dim=getMeshDimension();
1055 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1056 int nbOfCells=getNumberOfCells();
1059 const int *connIndex=_nodal_connec_index->getConstPointer();
1060 int *conn=_nodal_connec->getPointer();
1061 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1063 if(*iter>=0 && *iter<nbOfCells)
1065 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1066 if(!cm.isQuadratic())
1067 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1069 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1073 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1074 oss << " in range [0," << nbOfCells << ") !";
1075 throw INTERP_KERNEL::Exception(oss.str().c_str());
1081 int *connIndex=_nodal_connec_index->getPointer();
1082 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1083 const int *connOld=_nodal_connec->getConstPointer();
1084 int connOldLgth=_nodal_connec->getNbOfElems();
1085 std::vector<int> connNew(connOld,connOld+connOldLgth);
1086 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1088 if(*iter>=0 && *iter<nbOfCells)
1090 int pos=connIndex[*iter];
1091 int posP1=connIndex[(*iter)+1];
1092 int lgthOld=posP1-pos-1;
1093 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1094 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1095 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1096 int *tmp=new int[nbOfFaces*lgthOld];
1098 for(int j=0;j<(int)nbOfFaces;j++)
1100 INTERP_KERNEL::NormalizedCellType type;
1101 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1105 std::size_t newLgth=std::distance(tmp,work)-1;
1106 std::size_t delta=newLgth-lgthOld;
1107 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1108 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1109 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1114 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1115 oss << " in range [0," << nbOfCells << ") !";
1116 throw INTERP_KERNEL::Exception(oss.str().c_str());
1119 _nodal_connec->alloc((int)connNew.size(),1);
1120 int *newConnPtr=_nodal_connec->getPointer();
1121 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1127 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1128 * polyhedrons (if \a this is a 3D mesh).
1129 * \warning As this method is purely for user-friendliness and no optimization is
1130 * done to avoid construction of a useless vector, this method can be costly
1132 * \throw If the coordinates array is not set.
1133 * \throw If the nodal connectivity of cells is node defined.
1134 * \throw If dimension of \a this mesh is not either 2 or 3.
1136 void MEDCouplingUMesh::convertAllToPoly()
1138 int nbOfCells=getNumberOfCells();
1139 std::vector<int> cellIds(nbOfCells);
1140 for(int i=0;i<nbOfCells;i++)
1142 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1146 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1147 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1148 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1149 * base facet of the volume and the second half of nodes describes an opposite facet
1150 * having the same number of nodes as the base one. This method converts such
1151 * connectivity to a valid polyhedral format where connectivity of each facet is
1152 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1153 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1154 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1155 * a correct orientation of the first facet of a polyhedron, else orientation of a
1156 * corrected cell is reverse.<br>
1157 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1158 * it releases the user from boring description of polyhedra connectivity in the valid
1160 * \throw If \a this->getMeshDimension() != 3.
1161 * \throw If \a this->getSpaceDimension() != 3.
1162 * \throw If the nodal connectivity of cells is not defined.
1163 * \throw If the coordinates array is not set.
1164 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1165 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1167 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1168 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1170 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1172 checkFullyDefined();
1173 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1175 int nbOfCells=getNumberOfCells();
1176 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1177 newCi->alloc(nbOfCells+1,1);
1178 int *newci=newCi->getPointer();
1179 const int *ci=_nodal_connec_index->getConstPointer();
1180 const int *c=_nodal_connec->getConstPointer();
1182 for(int i=0;i<nbOfCells;i++)
1184 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1185 if(type==INTERP_KERNEL::NORM_POLYHED)
1187 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1189 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1190 throw INTERP_KERNEL::Exception(oss.str().c_str());
1192 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1195 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 !";
1196 throw INTERP_KERNEL::Exception(oss.str().c_str());
1199 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)
1202 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1204 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1205 newC->alloc(newci[nbOfCells],1);
1206 int *newc=newC->getPointer();
1207 for(int i=0;i<nbOfCells;i++)
1209 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1210 if(type==INTERP_KERNEL::NORM_POLYHED)
1212 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1213 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1215 for(std::size_t j=0;j<n1;j++)
1217 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1219 newc[n1+5*j+1]=c[ci[i]+1+j];
1220 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1221 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1222 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1227 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1229 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1230 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1235 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1236 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1237 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1238 * to write this mesh to the MED file, its cells must be sorted using
1239 * sortCellsInMEDFileFrmt().
1240 * \return \c true if at least one cell has been converted, \c false else. In the
1241 * last case the nodal connectivity remains unchanged.
1242 * \throw If the coordinates array is not set.
1243 * \throw If the nodal connectivity of cells is not defined.
1244 * \throw If \a this->getMeshDimension() < 0.
1246 bool MEDCouplingUMesh::unPolyze()
1248 checkFullyDefined();
1249 int mdim=getMeshDimension();
1251 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1254 int nbOfCells=getNumberOfCells();
1257 int initMeshLgth=getMeshLength();
1258 int *conn=_nodal_connec->getPointer();
1259 int *index=_nodal_connec_index->getPointer();
1264 for(int i=0;i<nbOfCells;i++)
1266 lgthOfCurCell=index[i+1]-posOfCurCell;
1267 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1268 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1269 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1273 switch(cm.getDimension())
1277 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1278 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1279 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1284 int nbOfFaces,lgthOfPolyhConn;
1285 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1286 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1291 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1295 ret=ret || (newType!=type);
1296 conn[newPos]=newType;
1298 posOfCurCell=index[i+1];
1303 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1304 newPos+=lgthOfCurCell;
1305 posOfCurCell+=lgthOfCurCell;
1309 if(newPos!=initMeshLgth)
1310 _nodal_connec->reAlloc(newPos);
1317 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1318 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1319 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1321 * \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
1324 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1326 checkFullyDefined();
1327 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1328 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1329 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1330 coords->recenterForMaxPrecision(eps);
1332 int nbOfCells=getNumberOfCells();
1333 const int *conn=_nodal_connec->getConstPointer();
1334 const int *index=_nodal_connec_index->getConstPointer();
1335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1336 connINew->alloc(nbOfCells+1,1);
1337 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1340 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1342 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1344 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1348 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1349 *connINewPtr=connNew->getNumberOfTuples();
1352 setConnectivity(connNew,connINew,false);
1356 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1357 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1358 * the format of returned DataArrayInt instance.
1360 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1361 * \sa MEDCouplingUMesh::getNodeIdsInUse
1363 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1365 checkConnectivityFullyDefined();
1366 int nbOfCells=getNumberOfCells();
1367 const int *connIndex=_nodal_connec_index->getConstPointer();
1368 const int *conn=_nodal_connec->getConstPointer();
1369 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1370 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1371 std::vector<bool> retS(maxElt,false);
1372 for(int i=0;i<nbOfCells;i++)
1373 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1377 for(int i=0;i<maxElt;i++)
1380 DataArrayInt *ret=DataArrayInt::New();
1382 int *retPtr=ret->getPointer();
1383 for(int i=0;i<maxElt;i++)
1390 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1391 * \sa MEDCouplingUMesh::getNodeIdsInUse
1393 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1395 int nbOfNodes=(int)nodeIdsInUse.size();
1396 int nbOfCells=getNumberOfCells();
1397 const int *connIndex=_nodal_connec_index->getConstPointer();
1398 const int *conn=_nodal_connec->getConstPointer();
1399 for(int i=0;i<nbOfCells;i++)
1400 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1403 if(conn[j]<nbOfNodes)
1404 nodeIdsInUse[conn[j]]=true;
1407 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1408 throw INTERP_KERNEL::Exception(oss.str().c_str());
1414 * Finds nodes not used in any cell and returns an array giving a new id to every node
1415 * by excluding the unused nodes, for which the array holds -1. The result array is
1416 * a mapping in "Old to New" mode.
1417 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1418 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1419 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1420 * if the node is unused or a new id else. The caller is to delete this
1421 * array using decrRef() as it is no more needed.
1422 * \throw If the coordinates array is not set.
1423 * \throw If the nodal connectivity of cells is not defined.
1424 * \throw If the nodal connectivity includes an invalid id.
1426 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1427 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1428 * \sa computeNodeIdsAlg()
1430 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1433 int nbOfNodes=getNumberOfNodes();
1434 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1435 ret->alloc(nbOfNodes,1);
1436 int *traducer=ret->getPointer();
1437 std::fill(traducer,traducer+nbOfNodes,-1);
1438 int nbOfCells=getNumberOfCells();
1439 const int *connIndex=_nodal_connec_index->getConstPointer();
1440 const int *conn=_nodal_connec->getConstPointer();
1441 for(int i=0;i<nbOfCells;i++)
1442 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1445 if(conn[j]<nbOfNodes)
1446 traducer[conn[j]]=1;
1449 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1450 throw INTERP_KERNEL::Exception(oss.str().c_str());
1453 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1454 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1459 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1460 * For each cell in \b this the number of nodes constituting cell is computed.
1461 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1462 * So for pohyhedrons some nodes can be counted several times in the returned result.
1464 * \return a newly allocated array
1466 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1468 checkConnectivityFullyDefined();
1469 int nbOfCells=getNumberOfCells();
1470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1471 ret->alloc(nbOfCells,1);
1472 int *retPtr=ret->getPointer();
1473 const int *conn=getNodalConnectivity()->getConstPointer();
1474 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1475 for(int i=0;i<nbOfCells;i++,retPtr++)
1477 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1478 *retPtr=connI[i+1]-connI[i]-1;
1480 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1486 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1487 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1489 * \return a newly allocated array
1491 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1493 checkConnectivityFullyDefined();
1494 int nbOfCells=getNumberOfCells();
1495 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1496 ret->alloc(nbOfCells,1);
1497 int *retPtr=ret->getPointer();
1498 const int *conn=getNodalConnectivity()->getConstPointer();
1499 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1500 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1502 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1503 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1509 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1510 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1511 * array mean that the corresponding old node is no more used.
1512 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1513 * this->getNumberOfNodes() before call of this method. The caller is to
1514 * delete this array using decrRef() as it is no more needed.
1515 * \throw If the coordinates array is not set.
1516 * \throw If the nodal connectivity of cells is not defined.
1517 * \throw If the nodal connectivity includes an invalid id.
1519 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1520 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1522 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1524 int newNbOfNodes=-1;
1525 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1526 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1531 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1532 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1534 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1539 return AreCellsEqual0(conn,connI,cell1,cell2);
1541 return AreCellsEqual1(conn,connI,cell1,cell2);
1543 return AreCellsEqual2(conn,connI,cell1,cell2);
1545 return AreCellsEqual3(conn,connI,cell1,cell2);
1547 return AreCellsEqual7(conn,connI,cell1,cell2);
1549 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1553 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1555 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1557 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1558 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1563 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1565 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1567 int sz=connI[cell1+1]-connI[cell1];
1568 if(sz==connI[cell2+1]-connI[cell2])
1570 if(conn[connI[cell1]]==conn[connI[cell2]])
1572 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1573 unsigned dim=cm.getDimension();
1579 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1580 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1581 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1582 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1583 return work!=tmp+sz1?1:0;
1586 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1589 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1596 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1598 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1600 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1602 if(conn[connI[cell1]]==conn[connI[cell2]])
1604 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1605 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1613 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1615 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1617 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1619 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1620 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1627 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1629 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1631 int sz=connI[cell1+1]-connI[cell1];
1632 if(sz==connI[cell2+1]-connI[cell2])
1634 if(conn[connI[cell1]]==conn[connI[cell2]])
1636 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1637 unsigned dim=cm.getDimension();
1643 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1644 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1645 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1646 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1651 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1652 std::reverse_iterator<int *> it2((int *)tmp);
1653 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1659 return work!=tmp+sz1?1:0;
1662 {//case of SEG2 and SEG3
1663 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1665 if(!cm.isQuadratic())
1667 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1668 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1669 if(std::equal(it1,it2,conn+connI[cell2]+1))
1675 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])
1682 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1690 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1691 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1693 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1695 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1697 std::vector<int> c1,c2;
1698 getNodeIdsOfCell(cellId,c1);
1699 other->getNodeIdsOfCell(cellId,c2);
1700 std::size_t sz=c1.size();
1703 for(std::size_t i=0;i<sz;i++)
1705 std::vector<double> n1,n2;
1706 getCoordinatesOfNode(c1[0],n1);
1707 other->getCoordinatesOfNode(c2[0],n2);
1708 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1709 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1710 if(*std::max_element(n1.begin(),n1.end())>prec)
1717 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1718 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1719 * and result remains unchanged.
1720 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1721 * If in 'candidates' pool -1 value is considered as an empty value.
1722 * WARNING this method returns only ONE set of result !
1724 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1726 if(candidates.size()<1)
1729 std::vector<int>::const_iterator iter=candidates.begin();
1730 int start=(*iter++);
1731 for(;iter!=candidates.end();iter++)
1733 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1738 result->pushBackSilent(start);
1742 result->pushBackSilent(*iter);
1744 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1751 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1752 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1754 * \param [in] compType input specifying the technique used to compare cells each other.
1755 * - 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.
1756 * - 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)
1757 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1758 * - 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
1759 * can be used for users not sensitive to orientation of cell
1760 * \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.
1761 * \param [out] commonCells
1762 * \param [out] commonCellsI
1763 * \return the correspondance array old to new in a newly allocated array.
1766 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1768 checkConnectivityFullyDefined();
1769 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1770 getReverseNodalConnectivity(revNodal,revNodalI);
1771 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1774 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1775 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1778 int nbOfCells=nodalI->getNumberOfTuples()-1;
1779 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1780 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1781 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1782 std::vector<bool> isFetched(nbOfCells,false);
1785 for(int i=0;i<nbOfCells;i++)
1789 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1790 std::vector<int> v,v2;
1791 if(connOfNode!=connPtr+connIPtr[i+1])
1793 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1794 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1797 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1801 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1802 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1803 v2.resize(std::distance(v2.begin(),it));
1807 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1809 int pos=commonCellsI->back();
1810 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1811 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1812 isFetched[*it]=true;
1820 for(int i=startCellId;i<nbOfCells;i++)
1824 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1825 std::vector<int> v,v2;
1826 if(connOfNode!=connPtr+connIPtr[i+1])
1828 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1831 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1835 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1836 v2.resize(std::distance(v2.begin(),it));
1840 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1842 int pos=commonCellsI->back();
1843 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1844 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1845 isFetched[*it]=true;
1851 commonCellsArr=commonCells.retn();
1852 commonCellsIArr=commonCellsI.retn();
1856 * Removes duplicates of cells from \a this mesh and returns an array mapping between
1857 * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1858 * equal cells found.
1859 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1860 * to write this mesh to the MED file, its cells must be sorted using
1861 * sortCellsInMEDFileFrmt().
1862 * \param [in] compType - specifies a cell comparison technique. Meaning of its
1863 * valid values [0,1,2] is as follows.
1864 * - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1865 * connectivity and type. This is the strongest policy.
1866 * - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1867 * are based on same nodes and have the same type and orientation.
1868 * - 2 : "nodal". Two cells are considered equal \c iff they
1869 * are based on same nodes and have the same type. This is the weakest
1870 * policy, it can be used by users not sensitive to cell orientation.
1871 * \param [in] startCellId - specifies the cell id at which search for equal cells
1872 * starts. By default it is 0, which means that all cells in \a this will be
1874 * \return DataArrayInt - a new instance of DataArrayInt, of length \a
1875 * this->getNumberOfCells() before call of this method. The caller is to
1876 * delete this array using decrRef() as it is no more needed.
1877 * \throw If the coordinates array is not set.
1878 * \throw If the nodal connectivity of cells is not defined.
1879 * \throw If the nodal connectivity includes an invalid id.
1881 * \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1882 * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1884 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1886 DataArrayInt *commonCells=0,*commonCellsI=0;
1887 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1888 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1889 int newNbOfCells=-1;
1890 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1891 commonCellsI->end(),newNbOfCells);
1892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1893 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1894 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1899 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1900 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1901 * than \a other->getNumberOfCells() in the returned array means that there is no
1902 * corresponding cell in \a this mesh.
1903 * It is expected that \a this and \a other meshes share the same node coordinates
1904 * array, if it is not so an exception is thrown.
1905 * \param [in] other - the mesh to compare with.
1906 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1907 * valid values [0,1,2], see zipConnectivityTraducer().
1908 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1909 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1910 * values. The caller is to delete this array using
1911 * decrRef() as it is no more needed.
1912 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1915 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1916 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1917 * \sa checkDeepEquivalOnSameNodesWith()
1918 * \sa checkGeoEquivalWith()
1920 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1922 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1923 int nbOfCells=getNumberOfCells();
1924 static const int possibleCompType[]={0,1,2};
1925 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1927 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1928 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1930 throw INTERP_KERNEL::Exception(oss.str().c_str());
1932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1933 arr=o2n->substr(nbOfCells);
1934 arr->setName(other->getName());
1936 if(other->getNumberOfCells()==0)
1938 return arr->getMaxValue(tmp)<nbOfCells;
1942 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1943 * This method tries to determine if \b other is fully included in \b this.
1944 * The main difference is that this method is not expected to throw exception.
1945 * This method has two outputs :
1947 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1948 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1950 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1952 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1953 DataArrayInt *commonCells=0,*commonCellsI=0;
1954 int thisNbCells=getNumberOfCells();
1955 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1957 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1958 int otherNbCells=other->getNumberOfCells();
1959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1960 arr2->alloc(otherNbCells,1);
1961 arr2->fillWithZero();
1962 int *arr2Ptr=arr2->getPointer();
1963 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1964 for(int i=0;i<nbOfCommon;i++)
1966 int start=commonCellsPtr[commonCellsIPtr[i]];
1967 if(start<thisNbCells)
1969 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1971 int sig=commonCellsPtr[j]>0?1:-1;
1972 int val=std::abs(commonCellsPtr[j])-1;
1973 if(val>=thisNbCells)
1974 arr2Ptr[val-thisNbCells]=sig*(start+1);
1978 arr2->setName(other->getName());
1979 if(arr2->presenceOfValue(0))
1986 * Merges nodes equal within \a precision and returns an array describing the
1987 * permutation used to remove duplicate nodes.
1988 * \param [in] precision - minimal absolute distance between two nodes at which they are
1989 * considered not coincident.
1990 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1991 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1992 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1993 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1994 * is to delete this array using decrRef() as it is no more needed.
1995 * \throw If the coordinates array is not set.
1996 * \throw If the nodal connectivity of cells is not defined.
1998 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1999 * \ref py_mcumesh_mergeNodes "Here is a Python example".
2001 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
2003 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2005 renumberNodes(ret->getConstPointer(),newNbOfNodes);
2011 * Merges nodes equal within \a precision and returns an array describing the
2012 * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
2013 * of merged nodes is changed to be at their barycenter.
2014 * \param [in] precision - minimal absolute distance between two nodes at which they are
2015 * considered not coincident.
2016 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
2017 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
2018 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
2019 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
2020 * is to delete this array using decrRef() as it is no more needed.
2021 * \throw If the coordinates array is not set.
2022 * \throw If the nodal connectivity of cells is not defined.
2024 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
2025 * \ref py_mcumesh_mergeNodes "Here is a Python example".
2027 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
2029 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2031 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
2036 * Substitutes node coordinates array of \a this mesh with that of \a other mesh
2037 * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
2038 * meshes match with a specified precision, else an exception is thrown and \a this
2039 * remains unchanged. In case of success the nodal connectivity of \a this mesh
2040 * is permuted according to new order of nodes.
2041 * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
2042 * coordinates (and so more expensive) than simple equality.
2043 * \param [in] other - the other mesh whose node coordinates array will be used by
2044 * \a this mesh in case of their equality.
2045 * \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
2046 * \throw If the coordinates array of \a this is not set.
2047 * \throw If the coordinates array of \a other is not set.
2048 * \throw If the coordinates of \a this and \a other do not match.
2050 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
2052 const DataArrayDouble *coords=other.getCoords();
2054 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
2056 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
2057 int otherNbOfNodes=other.getNumberOfNodes();
2058 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
2060 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
2061 setCoords(newCoords);
2062 bool areNodesMerged;
2064 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
2067 setCoords(oldCoords);
2068 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
2070 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
2071 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
2072 if(pt!=da->getConstPointer()+da->getNbOfElems())
2074 setCoords(oldCoords);
2075 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
2077 setCoords(oldCoords);
2078 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
2083 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2084 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2085 * cellIds is not given explicitely but by a range python like.
2087 * \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.
2088 * \return a newly allocated
2090 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2091 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2093 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
2095 if(getMeshDimension()!=-1)
2097 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
2104 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2106 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2108 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2110 return const_cast<MEDCouplingUMesh *>(this);
2115 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2116 * The result mesh shares or not the node coordinates array with \a this mesh depending
2117 * on \a keepCoords parameter.
2118 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2119 * to write this mesh to the MED file, its cells must be sorted using
2120 * sortCellsInMEDFileFrmt().
2121 * \param [in] begin - an array of cell ids to include to the new mesh.
2122 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2123 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2124 * array of \a this mesh, else "free" nodes are removed from the result mesh
2125 * by calling zipCoords().
2126 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2127 * to delete this mesh using decrRef() as it is no more needed.
2128 * \throw If the coordinates array is not set.
2129 * \throw If the nodal connectivity of cells is not defined.
2130 * \throw If any cell id in the array \a begin is not valid.
2132 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2133 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2135 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2137 if(getMeshDimension()!=-1)
2139 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
2147 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2149 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2151 return const_cast<MEDCouplingUMesh *>(this);
2156 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2158 * 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.
2159 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2160 * The number of cells of \b this will remain the same with this method.
2162 * \param [in] begin begin of cell ids (included) of cells in this to assign
2163 * \param [in] end end of cell ids (excluded) of cells in this to assign
2164 * \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).
2165 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2167 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2169 checkConnectivityFullyDefined();
2170 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2171 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2173 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2175 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2176 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2177 throw INTERP_KERNEL::Exception(oss.str().c_str());
2179 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2180 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2182 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2183 throw INTERP_KERNEL::Exception(oss.str().c_str());
2185 int nbOfCells=getNumberOfCells();
2186 bool easyAssign=true;
2187 const int *connI=_nodal_connec_index->getConstPointer();
2188 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2189 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2191 if(*it>=0 && *it<nbOfCells)
2193 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2197 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2198 throw INTERP_KERNEL::Exception(oss.str().c_str());
2203 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2208 DataArrayInt *arrOut=0,*arrIOut=0;
2209 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2212 setConnectivity(arrOut,arrIOut,true);
2216 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2218 checkConnectivityFullyDefined();
2219 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2220 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2221 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2222 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2224 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2225 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2226 throw INTERP_KERNEL::Exception(oss.str().c_str());
2228 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2229 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2231 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2232 throw INTERP_KERNEL::Exception(oss.str().c_str());
2234 int nbOfCells=getNumberOfCells();
2235 bool easyAssign=true;
2236 const int *connI=_nodal_connec_index->getConstPointer();
2237 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2239 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2241 if(it>=0 && it<nbOfCells)
2243 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2247 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2248 throw INTERP_KERNEL::Exception(oss.str().c_str());
2253 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2258 DataArrayInt *arrOut=0,*arrIOut=0;
2259 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2262 setConnectivity(arrOut,arrIOut,true);
2267 * Finds cells whose all nodes are in a given array of node ids.
2268 * \param [in] partBg - the array of node ids.
2269 * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2270 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2271 * cells. The caller is to delete this array using decrRef() as it is no
2273 * \throw If the coordinates array is not set.
2274 * \throw If the nodal connectivity of cells is not defined.
2275 * \throw If any cell id in \a partBg is not valid.
2277 * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2278 * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2280 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2282 DataArrayInt *cellIdsKept=0;
2283 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2284 cellIdsKept->setName(getName());
2289 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2290 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2291 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2292 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2294 * \param [in] begin input start of array of node ids.
2295 * \param [in] end input end of array of node ids.
2296 * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
2297 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2299 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2302 checkConnectivityFullyDefined();
2304 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2305 std::vector<bool> fastFinder(sz,false);
2306 for(const int *work=begin;work!=end;work++)
2307 if(*work>=0 && *work<sz)
2308 fastFinder[*work]=true;
2309 int nbOfCells=getNumberOfCells();
2310 const int *conn=getNodalConnectivity()->getConstPointer();
2311 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2312 for(int i=0;i<nbOfCells;i++)
2314 int ref=0,nbOfHit=0;
2315 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2319 if(fastFinder[*work2])
2322 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2323 cellIdsKept->pushBackSilent(i);
2325 cellIdsKeptArr=cellIdsKept.retn();
2329 * Finds cells whose all or some nodes are in a given array of node ids.
2330 * \param [in] begin - the array of node ids.
2331 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2332 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2333 * array \a begin are returned only, else cells whose any node is in the
2334 * array \a begin are returned.
2335 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2336 * cells. The caller is to delete this array using decrRef() as it is no more
2338 * \throw If the coordinates array is not set.
2339 * \throw If the nodal connectivity of cells is not defined.
2340 * \throw If any cell id in \a begin is not valid.
2342 * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2343 * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2345 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2347 DataArrayInt *cellIdsKept=0;
2348 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2349 cellIdsKept->setName(getName());
2354 Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
2355 copy are selected basing on specified node ids and the value of \a fullyIn
2356 parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the
2357 array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
2358 node is in the array of node ids. The created mesh shares the node coordinates array
2360 * \param [in] begin - the array of node ids.
2361 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2362 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2363 * array \a begin are copied, else cells whose any node is in the
2364 * array \a begin are copied.
2365 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2366 * to delete this mesh using decrRef() as it is no more needed.
2367 * \throw If the coordinates array is not set.
2368 * \throw If the nodal connectivity of cells is not defined.
2369 * \throw If any node id in \a begin is not valid.
2371 * \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
2372 * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
2374 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2376 DataArrayInt *cellIdsKept=0;
2377 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2379 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2383 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2384 * this->getMeshDimension(), that bound some cells of \a this mesh.
2385 * The cells of lower dimension to include to the result mesh are selected basing on
2386 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2387 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2388 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2389 * created mesh shares the node coordinates array with \a this mesh.
2390 * \param [in] begin - the array of node ids.
2391 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2392 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2393 * array \a begin are added, else cells whose any node is in the
2394 * array \a begin are added.
2395 * \return MEDCouplingPointSet * - 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.
2399 * \throw If any node id in \a begin is not valid.
2401 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2402 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2404 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2407 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2408 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2409 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2410 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2414 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2415 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2416 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2417 * array of \a this mesh, else "free" nodes are removed from the result mesh
2418 * by calling zipCoords().
2419 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2420 * to delete this mesh using decrRef() as it is no more needed.
2421 * \throw If the coordinates array is not set.
2422 * \throw If the nodal connectivity of cells is not defined.
2424 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2425 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2427 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2429 DataArrayInt *desc=DataArrayInt::New();
2430 DataArrayInt *descIndx=DataArrayInt::New();
2431 DataArrayInt *revDesc=DataArrayInt::New();
2432 DataArrayInt *revDescIndx=DataArrayInt::New();
2434 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2437 descIndx->decrRef();
2438 int nbOfCells=meshDM1->getNumberOfCells();
2439 const int *revDescIndxC=revDescIndx->getConstPointer();
2440 std::vector<int> boundaryCells;
2441 for(int i=0;i<nbOfCells;i++)
2442 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2443 boundaryCells.push_back(i);
2444 revDescIndx->decrRef();
2445 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2450 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2451 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2452 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
2454 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2456 checkFullyDefined();
2457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2462 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2463 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2467 const int *revDescPtr=revDesc->getConstPointer();
2468 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2469 int nbOfCells=getNumberOfCells();
2470 std::vector<bool> ret1(nbOfCells,false);
2472 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2473 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2474 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2476 DataArrayInt *ret2=DataArrayInt::New();
2478 int *ret2Ptr=ret2->getPointer();
2480 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2483 ret2->setName("BoundaryCells");
2488 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2489 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2490 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2491 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2493 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2494 * This method method returns cells ids set s = s1 + s2 where :
2496 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2497 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2499 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2500 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2502 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2503 * \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
2504 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2506 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2508 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2509 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2510 checkConnectivityFullyDefined();
2511 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2512 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2513 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2516 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2518 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2519 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2520 DataArrayInt *idsOtherInConsti=0;
2521 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2522 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2524 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2526 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2527 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2528 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2529 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2530 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2531 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2533 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2534 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2535 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2536 neighThisPartAuto=0;
2537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2538 const int li[2]={0,1};
2539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2540 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2541 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2544 cellIdsRk0=s0arr.retn();
2545 cellIdsRk1=s_renum1.retn();
2549 * 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
2550 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2552 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2554 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2556 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2561 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2562 revDesc=0; desc=0; descIndx=0;
2563 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2565 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2569 * Finds nodes lying on the boundary of \a this mesh.
2570 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2571 * nodes. The caller is to delete this array using decrRef() as it is no
2573 * \throw If the coordinates array is not set.
2574 * \throw If the nodal connectivity of cells is node defined.
2576 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2577 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2579 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2581 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2582 return skin->computeFetchedNodeIds();
2585 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2588 return const_cast<MEDCouplingUMesh *>(this);
2592 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2593 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
2594 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2595 * array is modified accordingly.
2596 * \param [in] newNodeNumbers - a permutation array, of length \a
2597 * this->getNumberOfNodes(), in "Old to New" mode.
2598 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2599 * \param [in] newNbOfNodes - number of nodes remaining after renumbering.
2600 * \throw If the coordinates array is not set.
2601 * \throw If the nodal connectivity of cells is not defined.
2603 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2604 * \ref py_mcumesh_renumberNodes "Here is a Python example".
2606 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2608 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2609 renumberNodesInConn(newNodeNumbers);
2613 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2614 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
2615 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2616 * array is modified accordingly. In contrast to renumberNodes(), location
2617 * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
2618 * \param [in] newNodeNumbers - a permutation array, of length \a
2619 * this->getNumberOfNodes(), in "Old to New" mode.
2620 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2621 * \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
2622 * actually one more than the maximal id in \a newNodeNumbers.
2623 * \throw If the coordinates array is not set.
2624 * \throw If the nodal connectivity of cells is not defined.
2626 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2627 * \ref py_mcumesh_renumberNodes "Here is a Python example".
2629 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2631 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2632 renumberNodesInConn(newNodeNumbers);
2636 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2637 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2638 * 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.
2639 * 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.
2640 * 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.
2642 * \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
2643 * parameter is altered during the call.
2644 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2645 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2646 * \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.
2648 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2650 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2651 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2653 checkFullyDefined();
2654 otherDimM1OnSameCoords.checkFullyDefined();
2655 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2657 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2658 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2659 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2660 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2663 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2664 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2668 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2670 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2671 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2672 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2673 DataArrayInt *idsTmp=0;
2674 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2675 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2677 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2678 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2679 DataArrayInt *tmp0=0,*tmp1=0;
2680 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2682 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2685 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2686 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2688 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2689 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2690 nodeIdsToDuplicate=s3.retn();
2694 * This method operates a modification of the connectivity and coords in \b this.
2695 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2696 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2697 * 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
2698 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2699 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2701 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2703 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2704 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2706 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2708 int nbOfNodes=getNumberOfNodes();
2709 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2710 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2714 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2715 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2716 * This method is a generalization of shiftNodeNumbersInConn().
2717 * \warning This method performs no check of validity of new ids. **Use it with care !**
2718 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2719 * this->getNumberOfNodes(), in "Old to New" mode.
2720 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2721 * \throw If the nodal connectivity of cells is not defined.
2723 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2724 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2726 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2728 checkConnectivityFullyDefined();
2729 int *conn=getNodalConnectivity()->getPointer();
2730 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2731 int nbOfCells=getNumberOfCells();
2732 for(int i=0;i<nbOfCells;i++)
2733 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2735 int& node=conn[iconn];
2736 if(node>=0)//avoid polyhedron separator
2738 node=newNodeNumbersO2N[node];
2741 _nodal_connec->declareAsNew();
2746 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2747 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2748 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2750 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2752 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2754 checkConnectivityFullyDefined();
2755 int *conn=getNodalConnectivity()->getPointer();
2756 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2757 int nbOfCells=getNumberOfCells();
2758 for(int i=0;i<nbOfCells;i++)
2759 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2761 int& node=conn[iconn];
2762 if(node>=0)//avoid polyhedron separator
2767 _nodal_connec->declareAsNew();
2772 * This method operates a modification of the connectivity in \b this.
2773 * 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.
2774 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2775 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2776 * 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
2777 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2778 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2780 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2781 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2783 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2784 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2785 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2787 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2789 checkConnectivityFullyDefined();
2790 std::map<int,int> m;
2792 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2794 int *conn=getNodalConnectivity()->getPointer();
2795 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2796 int nbOfCells=getNumberOfCells();
2797 for(int i=0;i<nbOfCells;i++)
2798 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2800 int& node=conn[iconn];
2801 if(node>=0)//avoid polyhedron separator
2803 std::map<int,int>::iterator it=m.find(node);
2812 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2814 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2815 * After the call of this method the number of cells remains the same as before.
2817 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2818 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2819 * be strictly in [0;this->getNumberOfCells()).
2821 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2822 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2823 * should be contained in[0;this->getNumberOfCells()).
2825 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2827 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2829 checkConnectivityFullyDefined();
2830 int nbCells=getNumberOfCells();
2831 const int *array=old2NewBg;
2833 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2835 const int *conn=_nodal_connec->getConstPointer();
2836 const int *connI=_nodal_connec_index->getConstPointer();
2837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2839 const int *n2oPtr=n2o->begin();
2840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2841 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2842 newConn->copyStringInfoFrom(*_nodal_connec);
2843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2844 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2845 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2847 int *newC=newConn->getPointer();
2848 int *newCI=newConnI->getPointer();
2851 for(int i=0;i<nbCells;i++)
2854 int nbOfElts=connI[pos+1]-connI[pos];
2855 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2860 setConnectivity(newConn,newConnI);
2862 free(const_cast<int *>(array));
2866 * Finds cells whose bounding boxes intersect a given bounding box.
2867 * \param [in] bbox - an array defining the bounding box via coordinates of its
2868 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2870 * \param [in] eps - a factor used to increase size of the bounding box of cell
2871 * before comparing it with \a bbox. This factor is multiplied by the maximal
2872 * extent of the bounding box of cell to produce an addition to this bounding box.
2873 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2874 * cells. The caller is to delete this array using decrRef() as it is no more
2876 * \throw If the coordinates array is not set.
2877 * \throw If the nodal connectivity of cells is not defined.
2879 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2880 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2882 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2885 if(getMeshDimension()==-1)
2887 elems->pushBackSilent(0);
2888 return elems.retn();
2890 int dim=getSpaceDimension();
2891 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2892 const int* conn = getNodalConnectivity()->getConstPointer();
2893 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2894 const double* coords = getCoords()->getConstPointer();
2895 int nbOfCells=getNumberOfCells();
2896 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2898 for (int i=0; i<dim; i++)
2900 elem_bb[i*2]=std::numeric_limits<double>::max();
2901 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2904 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2906 int node= conn[inode];
2907 if(node>=0)//avoid polyhedron separator
2909 for (int idim=0; idim<dim; idim++)
2911 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2913 elem_bb[idim*2] = coords[node*dim+idim] ;
2915 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2917 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2922 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2923 elems->pushBackSilent(ielem);
2925 return elems.retn();
2929 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2930 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2931 * added in 'elems' parameter.
2933 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2935 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2936 if(getMeshDimension()==-1)
2938 elems->pushBackSilent(0);
2939 return elems.retn();
2941 int dim=getSpaceDimension();
2942 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2943 const int* conn = getNodalConnectivity()->getConstPointer();
2944 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2945 const double* coords = getCoords()->getConstPointer();
2946 int nbOfCells=getNumberOfCells();
2947 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2949 for (int i=0; i<dim; i++)
2951 elem_bb[i*2]=std::numeric_limits<double>::max();
2952 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2955 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2957 int node= conn[inode];
2958 if(node>=0)//avoid polyhedron separator
2960 for (int idim=0; idim<dim; idim++)
2962 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2964 elem_bb[idim*2] = coords[node*dim+idim] ;
2966 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2968 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2973 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2974 elems->pushBackSilent(ielem);
2976 return elems.retn();
2980 * Returns a type of a cell by its id.
2981 * \param [in] cellId - the id of the cell of interest.
2982 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2983 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2985 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2987 const int *ptI=_nodal_connec_index->getConstPointer();
2988 const int *pt=_nodal_connec->getConstPointer();
2989 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2990 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2993 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2994 throw INTERP_KERNEL::Exception(oss.str().c_str());
2999 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
3000 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
3001 * The coordinates array is not considered here.
3003 * \param [in] type the geometric type
3004 * \return cell ids in this having geometric type \a type.
3006 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
3009 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
3011 checkConnectivityFullyDefined();
3012 int nbCells=getNumberOfCells();
3013 int mdim=getMeshDimension();
3014 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
3015 if(mdim!=(int)cm.getDimension())
3016 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
3017 const int *ptI=_nodal_connec_index->getConstPointer();
3018 const int *pt=_nodal_connec->getConstPointer();
3019 for(int i=0;i<nbCells;i++)
3021 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
3022 ret->pushBackSilent(i);
3028 * Returns nb of cells having the geometric type 'type'.
3030 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3032 const int *ptI=_nodal_connec_index->getConstPointer();
3033 const int *pt=_nodal_connec->getConstPointer();
3034 int nbOfCells=getNumberOfCells();
3036 for(int i=0;i<nbOfCells;i++)
3037 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3043 * Returns the nodal connectivity of a given cell.
3044 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3045 * all returned node ids can be used in getCoordinatesOfNode().
3046 * \param [in] cellId - an id of the cell of interest.
3047 * \param [in,out] conn - a vector where the node ids are appended. It is not
3048 * cleared before the appending.
3049 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3051 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3053 const int *ptI=_nodal_connec_index->getConstPointer();
3054 const int *pt=_nodal_connec->getConstPointer();
3055 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3060 std::string MEDCouplingUMesh::simpleRepr() const
3062 static const char msg0[]="No coordinates specified !";
3063 std::ostringstream ret;
3064 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3065 ret << "Description of mesh : \"" << getDescription() << "\"\n";
3067 double tt=getTime(tmpp1,tmpp2);
3068 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3069 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
3071 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3073 { ret << " Mesh dimension has not been set or is invalid !"; }
3076 const int spaceDim=getSpaceDimension();
3077 ret << spaceDim << "\nInfo attached on space dimension : ";
3078 for(int i=0;i<spaceDim;i++)
3079 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3083 ret << msg0 << "\n";
3084 ret << "Number of nodes : ";
3086 ret << getNumberOfNodes() << "\n";
3088 ret << msg0 << "\n";
3089 ret << "Number of cells : ";
3090 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3091 ret << getNumberOfCells() << "\n";
3093 ret << "No connectivity specified !" << "\n";
3094 ret << "Cell types present : ";
3095 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3097 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3098 ret << cm.getRepr() << " ";
3104 std::string MEDCouplingUMesh::advancedRepr() const
3106 std::ostringstream ret;
3107 ret << simpleRepr();
3108 ret << "\nCoordinates array : \n___________________\n\n";
3110 _coords->reprWithoutNameStream(ret);
3112 ret << "No array set !\n";
3113 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3114 reprConnectivityOfThisLL(ret);
3119 * This method returns a C++ code that is a dump of \a this.
3120 * This method will throw if this is not fully defined.
3122 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
3124 static const char coordsName[]="coords";
3125 static const char connName[]="conn";
3126 static const char connIName[]="connI";
3127 checkFullyDefined();
3128 std::ostringstream ret; ret << "// coordinates" << std::endl;
3129 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3130 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3131 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3132 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3133 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3134 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3135 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3139 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3141 std::ostringstream ret;
3142 reprConnectivityOfThisLL(ret);
3147 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
3148 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3149 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3152 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3153 * 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
3154 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3156 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
3158 int mdim=getMeshDimension();
3160 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3161 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3163 bool needToCpyCT=true;
3166 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3174 if(!_nodal_connec_index)
3176 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3181 tmp2=_nodal_connec_index;
3184 ret->setConnectivity(tmp1,tmp2,false);
3189 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3190 ret->setCoords(coords);
3193 ret->setCoords(_coords);
3197 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3199 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3201 int nbOfCells=getNumberOfCells();
3202 const int *c=_nodal_connec->getConstPointer();
3203 const int *ci=_nodal_connec_index->getConstPointer();
3204 for(int i=0;i<nbOfCells;i++)
3206 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3207 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3208 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3213 stream << "Connectivity not defined !\n";
3216 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3218 const int *ptI=_nodal_connec_index->getConstPointer();
3219 const int *pt=_nodal_connec->getConstPointer();
3220 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3221 return ptI[cellId+1]-ptI[cellId]-1;
3223 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3227 * Returns types of cells of the specified part of \a this mesh.
3228 * This method avoids computing sub-mesh explicitely to get its types.
3229 * \param [in] begin - an array of cell ids of interest.
3230 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3231 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3232 * describing the cell types.
3233 * \throw If the coordinates array is not set.
3234 * \throw If the nodal connectivity of cells is not defined.
3237 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
3239 checkFullyDefined();
3240 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3241 const int *conn=_nodal_connec->getConstPointer();
3242 const int *connIndex=_nodal_connec_index->getConstPointer();
3243 for(const int *w=begin;w!=end;w++)
3244 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3249 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3250 * a set of types of cells constituting \a this mesh.
3251 * This method is for advanced users having prepared their connectivity before. For
3252 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3253 * \param [in] conn - the nodal connectivity array.
3254 * \param [in] connIndex - the nodal connectivity index array.
3255 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3258 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3260 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3261 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3262 if(isComputingTypes)
3268 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
3269 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3271 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3272 _nodal_connec(0),_nodal_connec_index(0),
3273 _types(other._types)
3275 if(other._nodal_connec)
3276 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3277 if(other._nodal_connec_index)
3278 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3281 MEDCouplingUMesh::~MEDCouplingUMesh()
3284 _nodal_connec->decrRef();
3285 if(_nodal_connec_index)
3286 _nodal_connec_index->decrRef();
3290 * Recomputes a set of cell types of \a this mesh. For more info see
3291 * \ref MEDCouplingUMeshNodalConnectivity.
3293 void MEDCouplingUMesh::computeTypes()
3295 if(_nodal_connec && _nodal_connec_index)
3298 const int *conn=_nodal_connec->getConstPointer();
3299 const int *connIndex=_nodal_connec_index->getConstPointer();
3300 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3302 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3303 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3308 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3310 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3312 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3313 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3317 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3319 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3321 if(!_nodal_connec_index || !_nodal_connec)
3322 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3326 * Returns a number of cells constituting \a this mesh.
3327 * \return int - the number of cells in \a this mesh.
3328 * \throw If the nodal connectivity of cells is not defined.
3330 int MEDCouplingUMesh::getNumberOfCells() const
3332 if(_nodal_connec_index)
3333 return _nodal_connec_index->getNumberOfTuples()-1;
3338 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3342 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3343 * mesh. For more info see \ref MEDCouplingMeshesPage.
3344 * \return int - the dimension of \a this mesh.
3345 * \throw If the mesh dimension is not defined using setMeshDimension().
3347 int MEDCouplingUMesh::getMeshDimension() const
3350 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3355 * Returns a length of the nodal connectivity array.
3356 * This method is for test reason. Normally the integer returned is not useable by
3357 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3358 * \return int - the length of the nodal connectivity array.
3360 int MEDCouplingUMesh::getMeshLength() const
3362 return _nodal_connec->getNbOfElems();
3366 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3368 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3370 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3371 tinyInfo.push_back(getMeshDimension());
3372 tinyInfo.push_back(getNumberOfCells());
3374 tinyInfo.push_back(getMeshLength());
3376 tinyInfo.push_back(-1);
3380 * First step of unserialization process.
3382 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3384 return tinyInfo[6]<=0;
3388 * Second step of serialization process.
3389 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3391 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3393 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3395 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3399 * Third and final step of serialization process.
3401 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3403 MEDCouplingPointSet::serialize(a1,a2);
3404 if(getMeshDimension()>-1)
3406 a1=DataArrayInt::New();
3407 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3408 int *ptA1=a1->getPointer();
3409 const int *conn=getNodalConnectivity()->getConstPointer();
3410 const int *index=getNodalConnectivityIndex()->getConstPointer();
3411 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3412 std::copy(conn,conn+getMeshLength(),ptA1);
3419 * Second and final unserialization process.
3420 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3422 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3424 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3425 setMeshDimension(tinyInfo[5]);
3429 const int *recvBuffer=a1->getConstPointer();
3430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3431 myConnecIndex->alloc(tinyInfo[6]+1,1);
3432 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3434 myConnec->alloc(tinyInfo[7],1);
3435 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3436 setConnectivity(myConnec, myConnecIndex);
3441 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3442 * CellIds are given using range specified by a start an end and step.
3444 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3446 checkFullyDefined();
3447 int ncell=getNumberOfCells();
3448 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3449 ret->_mesh_dim=_mesh_dim;
3450 ret->setCoords(_coords);
3451 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3453 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3455 const int *conn=_nodal_connec->getConstPointer();
3456 const int *connIndex=_nodal_connec_index->getConstPointer();
3457 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3459 if(work>=0 && work<ncell)
3461 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3465 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3466 throw INTERP_KERNEL::Exception(oss.str().c_str());
3469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3470 int *newConnPtr=newConn->getPointer();
3471 std::set<INTERP_KERNEL::NormalizedCellType> types;
3473 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3475 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3476 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3478 ret->setConnectivity(newConn,newConnI,false);
3480 ret->copyTinyInfoFrom(this);
3485 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3486 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3487 * The return newly allocated mesh will share the same coordinates as 'this'.
3489 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3491 checkFullyDefined();
3492 int ncell=getNumberOfCells();
3493 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3494 ret->_mesh_dim=_mesh_dim;
3495 ret->setCoords(_coords);
3496 std::size_t nbOfElemsRet=std::distance(begin,end);
3497 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3499 const int *conn=_nodal_connec->getConstPointer();
3500 const int *connIndex=_nodal_connec_index->getConstPointer();
3502 for(const int *work=begin;work!=end;work++,newNbring++)
3504 if(*work>=0 && *work<ncell)
3505 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3509 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3510 throw INTERP_KERNEL::Exception(oss.str().c_str());
3513 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3514 int *connRetWork=connRet;
3515 std::set<INTERP_KERNEL::NormalizedCellType> types;
3516 for(const int *work=begin;work!=end;work++)
3518 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3519 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3521 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3522 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3524 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3525 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3527 ret->copyTinyInfoFrom(this);
3532 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3534 * For 1D cells, the returned field contains lengths.<br>
3535 * For 2D cells, the returned field contains areas.<br>
3536 * For 3D cells, the returned field contains volumes.
3537 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3538 * orientation, i.e. the volume is always positive.
3539 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3540 * and one time . The caller is to delete this field using decrRef() as it is no
3543 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3545 std::string name="MeasureOfMesh_";
3547 int nbelem=getNumberOfCells();
3548 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3549 field->setName(name.c_str());
3550 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3551 array->alloc(nbelem,1);
3552 double *area_vol=array->getPointer();
3553 field->setArray(array) ; array=0;
3554 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3555 field->synchronizeTimeWithMesh();
3556 if(getMeshDimension()!=-1)
3559 INTERP_KERNEL::NormalizedCellType type;
3560 int dim_space=getSpaceDimension();
3561 const double *coords=getCoords()->getConstPointer();
3562 const int *connec=getNodalConnectivity()->getConstPointer();
3563 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3564 for(int iel=0;iel<nbelem;iel++)
3566 ipt=connec_index[iel];
3567 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3568 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);
3571 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3575 area_vol[0]=std::numeric_limits<double>::max();
3577 return field.retn();
3581 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3583 * For 1D cells, the returned array contains lengths.<br>
3584 * For 2D cells, the returned array contains areas.<br>
3585 * For 3D cells, the returned array contains volumes.
3586 * This method avoids building explicitly a part of \a this mesh to perform the work.
3587 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3588 * orientation, i.e. the volume is always positive.
3589 * \param [in] begin - an array of cell ids of interest.
3590 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3591 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3592 * delete this array using decrRef() as it is no more needed.
3594 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3595 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3596 * \sa getMeasureField()
3598 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3600 std::string name="PartMeasureOfMesh_";
3602 int nbelem=(int)std::distance(begin,end);
3603 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3604 array->setName(name.c_str());
3605 array->alloc(nbelem,1);
3606 double *area_vol=array->getPointer();
3607 if(getMeshDimension()!=-1)
3610 INTERP_KERNEL::NormalizedCellType type;
3611 int dim_space=getSpaceDimension();
3612 const double *coords=getCoords()->getConstPointer();
3613 const int *connec=getNodalConnectivity()->getConstPointer();
3614 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3615 for(const int *iel=begin;iel!=end;iel++)
3617 ipt=connec_index[*iel];
3618 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3619 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3622 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3626 area_vol[0]=std::numeric_limits<double>::max();
3628 return array.retn();
3632 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3633 * \a this one. The returned field contains the dual cell volume for each corresponding
3634 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3635 * the dual mesh in P1 sens of \a this.<br>
3636 * For 1D cells, the returned field contains lengths.<br>
3637 * For 2D cells, the returned field contains areas.<br>
3638 * For 3D cells, the returned field contains volumes.
3639 * This method is useful to check "P1*" conservative interpolators.
3640 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3641 * orientation, i.e. the volume is always positive.
3642 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3643 * nodes and one time. The caller is to delete this array using decrRef() as
3644 * it is no more needed.
3646 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3648 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3649 std::string name="MeasureOnNodeOfMesh_";
3651 int nbNodes=getNumberOfNodes();
3652 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3653 double cst=1./((double)getMeshDimension()+1.);
3654 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3655 array->alloc(nbNodes,1);
3656 double *valsToFill=array->getPointer();
3657 std::fill(valsToFill,valsToFill+nbNodes,0.);
3658 const double *values=tmp->getArray()->getConstPointer();
3659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3661 getReverseNodalConnectivity(da,daInd);
3662 const int *daPtr=da->getConstPointer();
3663 const int *daIPtr=daInd->getConstPointer();
3664 for(int i=0;i<nbNodes;i++)
3665 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3666 valsToFill[i]+=cst*values[*cell];
3668 ret->setArray(array);
3673 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3674 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3675 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3676 * and are normalized.
3677 * <br> \a this can be either
3678 * - a 2D mesh in 2D or 3D space or
3679 * - an 1D mesh in 2D space.
3681 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3682 * cells and one time. The caller is to delete this field using decrRef() as
3683 * it is no more needed.
3684 * \throw If the nodal connectivity of cells is not defined.
3685 * \throw If the coordinates array is not set.
3686 * \throw If the mesh dimension is not set.
3687 * \throw If the mesh and space dimension is not as specified above.
3689 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3691 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3692 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3693 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3694 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3695 int nbOfCells=getNumberOfCells();
3696 int nbComp=getMeshDimension()+1;
3697 array->alloc(nbOfCells,nbComp);
3698 double *vals=array->getPointer();
3699 const int *connI=_nodal_connec_index->getConstPointer();
3700 const int *conn=_nodal_connec->getConstPointer();
3701 const double *coords=_coords->getConstPointer();
3702 if(getMeshDimension()==2)
3704 if(getSpaceDimension()==3)
3706 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3707 const double *locPtr=loc->getConstPointer();
3708 for(int i=0;i<nbOfCells;i++,vals+=3)
3710 int offset=connI[i];
3711 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3712 double n=INTERP_KERNEL::norm<3>(vals);
3713 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3718 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3719 const double *isAbsPtr=isAbs->getArray()->begin();
3720 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3721 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3724 else//meshdimension==1
3727 for(int i=0;i<nbOfCells;i++)
3729 int offset=connI[i];
3730 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3731 double n=INTERP_KERNEL::norm<2>(tmp);
3732 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3737 ret->setArray(array);
3739 ret->synchronizeTimeWithSupport();
3744 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3745 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3746 * and are normalized.
3747 * <br> \a this can be either
3748 * - a 2D mesh in 2D or 3D space or
3749 * - an 1D mesh in 2D space.
3751 * This method avoids building explicitly a part of \a this mesh to perform the work.
3752 * \param [in] begin - an array of cell ids of interest.
3753 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3754 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3755 * cells and one time. The caller is to delete this field using decrRef() as
3756 * it is no more needed.
3757 * \throw If the nodal connectivity of cells is not defined.
3758 * \throw If the coordinates array is not set.
3759 * \throw If the mesh dimension is not set.
3760 * \throw If the mesh and space dimension is not as specified above.
3761 * \sa buildOrthogonalField()
3763 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3764 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3766 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3768 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3769 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3770 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3771 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3772 std::size_t nbelems=std::distance(begin,end);
3773 int nbComp=getMeshDimension()+1;
3774 array->alloc((int)nbelems,nbComp);
3775 double *vals=array->getPointer();
3776 const int *connI=_nodal_connec_index->getConstPointer();
3777 const int *conn=_nodal_connec->getConstPointer();
3778 const double *coords=_coords->getConstPointer();
3779 if(getMeshDimension()==2)
3781 if(getSpaceDimension()==3)
3783 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3784 const double *locPtr=loc->getConstPointer();
3785 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3787 int offset=connI[*i];
3788 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3789 double n=INTERP_KERNEL::norm<3>(vals);
3790 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3795 for(std::size_t i=0;i<nbelems;i++)
3796 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3799 else//meshdimension==1
3802 for(const int *i=begin;i!=end;i++)
3804 int offset=connI[*i];
3805 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3806 double n=INTERP_KERNEL::norm<2>(tmp);
3807 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3812 ret->setArray(array);
3814 ret->synchronizeTimeWithSupport();
3819 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3820 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3821 * and are \b not normalized.
3822 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3823 * cells and one time. The caller is to delete this field using decrRef() as
3824 * it is no more needed.
3825 * \throw If the nodal connectivity of cells is not defined.
3826 * \throw If the coordinates array is not set.
3827 * \throw If \a this->getMeshDimension() != 1.
3828 * \throw If \a this mesh includes cells of type other than SEG2.
3830 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3832 if(getMeshDimension()!=1)
3833 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3834 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3835 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3836 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3837 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3838 int nbOfCells=getNumberOfCells();
3839 int spaceDim=getSpaceDimension();
3840 array->alloc(nbOfCells,spaceDim);
3841 double *pt=array->getPointer();
3842 const double *coo=getCoords()->getConstPointer();
3843 std::vector<int> conn;
3845 for(int i=0;i<nbOfCells;i++)
3848 getNodeIdsOfCell(i,conn);
3849 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3851 ret->setArray(array);
3853 ret->synchronizeTimeWithSupport();
3858 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3859 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3860 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3861 * from. If a result face is shared by two 3D cells, then the face in included twice in
3863 * \param [in] origin - 3 components of a point defining location of the plane.
3864 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3865 * must be greater than 1e-6.
3866 * \param [in] eps - half-thickness of the plane.
3867 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3868 * producing correspondent 2D cells. The caller is to delete this array
3869 * using decrRef() as it is no more needed.
3870 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3871 * not share the node coordinates array with \a this mesh. The caller is to
3872 * delete this mesh using decrRef() as it is no more needed.
3873 * \throw If the coordinates array is not set.
3874 * \throw If the nodal connectivity of cells is not defined.
3875 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3876 * \throw If magnitude of \a vec is less than 1e-6.
3877 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3878 * \throw If \a this includes quadratic cells.
3880 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3882 checkFullyDefined();
3883 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3884 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3886 if(candidates->empty())
3887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3888 std::vector<int> nodes;
3889 DataArrayInt *cellIds1D=0;
3890 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3891 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3896 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3897 revDesc2=0; revDescIndx2=0;
3898 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3899 revDesc1=0; revDescIndx1=0;
3900 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3903 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3904 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3906 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3907 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3908 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3909 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3910 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3912 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3913 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3914 if(cellIds2->empty())
3915 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3916 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3917 ret->setCoords(mDesc1->getCoords());
3918 ret->setConnectivity(conn,connI,true);
3919 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3924 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3925 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
3926 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3928 * \param [in] origin - 3 components of a point defining location of the plane.
3929 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3930 * must be greater than 1e-6.
3931 * \param [in] eps - half-thickness of the plane.
3932 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3933 * producing correspondent segments. The caller is to delete this array
3934 * using decrRef() as it is no more needed.
3935 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3936 * mesh in 3D space. This mesh does not share the node coordinates array with
3937 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3939 * \throw If the coordinates array is not set.
3940 * \throw If the nodal connectivity of cells is not defined.
3941 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3942 * \throw If magnitude of \a vec is less than 1e-6.
3943 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3944 * \throw If \a this includes quadratic cells.
3946 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3948 checkFullyDefined();
3949 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3950 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3952 if(candidates->empty())
3953 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3954 std::vector<int> nodes;
3955 DataArrayInt *cellIds1D=0;
3956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3957 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3958 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3963 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3966 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3967 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3969 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3970 int ncellsSub=subMesh->getNumberOfCells();
3971 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3972 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3973 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3974 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3977 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3978 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3979 for(int i=0;i<ncellsSub;i++)
3981 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3983 if(cut3DSurf[i].first!=-2)
3985 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3986 connI->pushBackSilent(conn->getNumberOfTuples());
3987 cellIds2->pushBackSilent(i);
3991 int cellId3DSurf=cut3DSurf[i].second;
3992 int offset=nodalI[cellId3DSurf]+1;
3993 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3994 for(int j=0;j<nbOfEdges;j++)
3996 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3997 connI->pushBackSilent(conn->getNumberOfTuples());
3998 cellIds2->pushBackSilent(cellId3DSurf);
4003 if(cellIds2->empty())
4004 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
4005 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
4006 ret->setCoords(mDesc1->getCoords());
4007 ret->setConnectivity(conn,connI,true);
4008 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
4013 * Finds cells whose bounding boxes intersect a given plane.
4014 * \param [in] origin - 3 components of a point defining location of the plane.
4015 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
4016 * must be greater than 1e-6.
4017 * \param [in] eps - half-thickness of the plane.
4018 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
4019 * cells. The caller is to delete this array using decrRef() as it is no more
4021 * \throw If the coordinates array is not set.
4022 * \throw If the nodal connectivity of cells is not defined.
4023 * \throw If \a this->getSpaceDimension() != 3.
4024 * \throw If magnitude of \a vec is less than 1e-6.
4025 * \sa buildSlice3D()
4027 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
4029 checkFullyDefined();
4030 if(getSpaceDimension()!=3)
4031 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4032 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4034 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4036 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4037 double angle=acos(vec[2]/normm);
4038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
4042 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
4043 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4044 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4046 mw->getBoundingBox(bbox);
4047 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4048 cellIds=mw->getCellsInBoundingBox(bbox,eps);
4052 getBoundingBox(bbox);
4053 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4054 cellIds=getCellsInBoundingBox(bbox,eps);
4056 return cellIds.retn();
4060 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4061 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4062 * No consideration of coordinate is done by this method.
4063 * 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)
4064 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
4066 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
4068 if(getMeshDimension()!=1)
4069 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4070 int nbCells=getNumberOfCells();
4072 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4073 const int *connI=_nodal_connec_index->getConstPointer();
4074 const int *conn=_nodal_connec->getConstPointer();
4075 int ref=conn[connI[0]+2];
4076 for(int i=1;i<nbCells;i++)
4078 if(conn[connI[i]+1]!=ref)
4080 ref=conn[connI[i]+2];
4086 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4087 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4088 * @param pt reference point of the line
4089 * @param v normalized director vector of the line
4090 * @param eps max precision before throwing an exception
4091 * @param res output of size this->getNumberOfCells
4093 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4095 if(getMeshDimension()!=1)
4096 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4097 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4098 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4099 if(getSpaceDimension()!=3)
4100 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4101 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4102 const double *fPtr=f->getArray()->getConstPointer();
4104 for(int i=0;i<getNumberOfCells();i++)
4106 const double *tmp1=fPtr+3*i;
4107 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4108 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4109 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4110 double n1=INTERP_KERNEL::norm<3>(tmp);
4111 n1/=INTERP_KERNEL::norm<3>(tmp1);
4113 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4115 const double *coo=getCoords()->getConstPointer();
4116 for(int i=0;i<getNumberOfNodes();i++)
4118 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4119 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4120 res[i]=std::accumulate(tmp,tmp+3,0.);
4125 * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance.
4126 * \a this is expected to be a mesh so that its space dimension is equal to its
4127 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4128 * 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).
4130 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4131 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4132 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4134 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4135 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4137 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4138 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4139 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4140 * \return the positive value of the distance.
4141 * \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
4143 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4145 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
4147 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4148 if(meshDim!=spaceDim-1)
4149 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4150 if(meshDim!=2 && meshDim!=1)
4151 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4152 checkFullyDefined();
4153 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4154 { 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()); }
4155 DataArrayInt *ret1=0;
4156 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4157 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4158 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4159 cellId=*ret1Safe->begin();
4160 return *ret0->begin();
4164 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4165 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4166 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4167 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4168 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4170 * \a this is expected to be a mesh so that its space dimension is equal to its
4171 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4172 * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
4174 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4175 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4177 * \param [in] pts the list of points in which each tuple represents a point
4178 * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
4179 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4180 * \throw if number of components of \a pts is not equal to the space dimension.
4181 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4182 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4184 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
4187 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4188 pts->checkAllocated();
4189 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4190 if(meshDim!=spaceDim-1)
4191 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4192 if(meshDim!=2 && meshDim!=1)
4193 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4194 if(pts->getNumberOfComponents()!=spaceDim)
4196 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4197 throw INTERP_KERNEL::Exception(oss.str().c_str());
4199 checkFullyDefined();
4200 int nbCells=getNumberOfCells();
4202 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4203 int nbOfPts=pts->getNumberOfTuples();
4204 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4206 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4207 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4208 std::vector<double> bbox;
4209 getBoundingBoxForBBTree(bbox);
4214 BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
4215 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4217 double x=std::numeric_limits<double>::max();
4218 std::vector<int> elems;
4219 myTree.getMinDistanceOfMax(ptsPtr,x);
4220 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4221 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4227 BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
4228 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4230 double x=std::numeric_limits<double>::max();
4231 std::vector<int> elems;
4232 myTree.getMinDistanceOfMax(ptsPtr,x);
4233 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4234 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4239 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4241 cellIds=ret1.retn();
4246 * \param [in] pt the start pointer (included) of the coordinates of the point
4247 * \param [in] cellIdsBg the start pointer (included) of cellIds
4248 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4249 * \param [in] nc nodal connectivity
4250 * \param [in] ncI nodal connectivity index
4251 * \param [in,out] ret0 the min distance between \a this and the external input point
4252 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4253 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4255 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
4258 ret0=std::numeric_limits<double>::max();
4259 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4261 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4263 case INTERP_KERNEL::NORM_TRI3:
4265 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4267 { ret0=tmp; cellId=*zeCell; }
4270 case INTERP_KERNEL::NORM_QUAD4:
4271 case INTERP_KERNEL::NORM_POLYGON:
4273 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4275 { ret0=tmp; cellId=*zeCell; }
4279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4285 * \param [in] pt the start pointer (included) of the coordinates of the point
4286 * \param [in] cellIdsBg the start pointer (included) of cellIds
4287 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4288 * \param [in] nc nodal connectivity
4289 * \param [in] ncI nodal connectivity index
4290 * \param [in,out] ret0 the min distance between \a this and the external input point
4291 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4292 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4294 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
4297 ret0=std::numeric_limits<double>::max();
4298 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4300 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4302 case INTERP_KERNEL::NORM_SEG2:
4304 std::size_t uselessEntry=0;
4305 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4308 { ret0=tmp; cellId=*zeCell; }
4312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4318 * Finds cells in contact with a ball (i.e. a point with precision).
4319 * \warning This method is suitable if the caller intends to evaluate only one
4320 * point, for more points getCellsContainingPoints() is recommended as it is
4322 * \param [in] pos - array of coordinates of the ball central point.
4323 * \param [in] eps - ball radius.
4324 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4325 * if there are no such cells.
4326 * \throw If the coordinates array is not set.
4327 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4329 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4331 std::vector<int> elts;
4332 getCellsContainingPoint(pos,eps,elts);
4335 return elts.front();
4339 * Finds cells in contact with a ball (i.e. a point with precision).
4340 * \warning This method is suitable if the caller intends to evaluate only one
4341 * point, for more points getCellsContainingPoints() is recommended as it is
4343 * \param [in] pos - array of coordinates of the ball central point.
4344 * \param [in] eps - ball radius.
4345 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
4346 * before inserting ids.
4347 * \throw If the coordinates array is not set.
4348 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4350 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4351 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4353 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4355 std::vector<int> eltsIndex;
4356 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4361 namespace ParaMEDMEM
4363 template<const int SPACEDIMM>
4367 static const int MY_SPACEDIM=SPACEDIMM;
4368 static const int MY_MESHDIM=8;
4369 typedef int MyConnType;
4370 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4372 // useless, but for windows compilation ...
4373 const double* getCoordinatesPtr() const { return 0; }
4374 const int* getConnectivityPtr() const { return 0; }
4375 const int* getConnectivityIndexPtr() const { return 0; }
4376 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4380 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4382 INTERP_KERNEL::Edge *ret=0;
4385 case INTERP_KERNEL::NORM_SEG2:
4387 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4390 case INTERP_KERNEL::NORM_SEG3:
4392 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4393 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4394 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4395 bool colinearity=inters.areColinears();
4396 delete e1; delete e2;
4398 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4400 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4401 mapp2[bg[2]].second=false;
4405 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4411 * 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'.
4412 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4413 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4415 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4418 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.
4419 const double *coo=mDesc->getCoords()->getConstPointer();
4420 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4421 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4423 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4424 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4425 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4427 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4428 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4430 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4431 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4433 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4434 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4436 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4438 if((*it2).second.second)
4439 mapp[(*it2).second.first]=(*it2).first;
4440 ((*it2).second.first)->decrRef();
4445 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4449 int locId=nodeId-offset2;
4450 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4454 int locId=nodeId-offset1;
4455 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4457 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4460 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4461 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4462 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4464 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4466 int eltId1=abs(*desc1)-1;
4467 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4469 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4470 if(it==mappRev.end())
4472 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4483 template<int SPACEDIM>
4484 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4485 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4487 std::vector<double> bbox;
4488 eltsIndex.resize(nbOfPoints+1);
4491 getBoundingBoxForBBTree(bbox);
4492 int nbOfCells=getNumberOfCells();
4493 const int *conn=_nodal_connec->getConstPointer();
4494 const int *connI=_nodal_connec_index->getConstPointer();
4495 double bb[2*SPACEDIM];
4496 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4497 for(int i=0;i<nbOfPoints;i++)
4499 eltsIndex[i+1]=eltsIndex[i];
4500 for(int j=0;j<SPACEDIM;j++)
4502 bb[2*j]=pos[SPACEDIM*i+j];
4503 bb[2*j+1]=pos[SPACEDIM*i+j];
4505 std::vector<int> candidates;
4506 myTree.getIntersectingElems(bb,candidates);
4507 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4509 int sz=connI[(*iter)+1]-connI[*iter]-1;
4510 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4511 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4512 coords,conn+connI[*iter]+1,sz,eps))
4515 elts.push_back(*iter);
4521 * Finds cells in contact with several balls (i.e. points with precision).
4522 * This method is an extension of getCellContainingPoint() and
4523 * getCellsContainingPoint() for the case of multiple points.
4524 * \param [in] pos - an array of coordinates of points in full interlace mode :
4525 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4526 * this->getSpaceDimension() * \a nbOfPoints
4527 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4528 * \param [in] eps - radius of balls (i.e. the precision).
4529 * \param [in,out] elts - vector returning ids of found cells.
4530 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4531 * dividing cell ids in \a elts into groups each referring to one
4532 * point. Its every element (except the last one) is an index pointing to the
4533 * first id of a group of cells. For example cells in contact with the *i*-th
4534 * point are described by following range of indices:
4535 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4536 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4537 * Number of cells in contact with the *i*-th point is
4538 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4539 * \throw If the coordinates array is not set.
4540 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4542 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4543 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4545 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4546 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4548 int spaceDim=getSpaceDimension();
4549 int mDim=getMeshDimension();
4554 const double *coords=_coords->getConstPointer();
4555 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4562 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4564 else if(spaceDim==2)
4568 const double *coords=_coords->getConstPointer();
4569 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4572 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4574 else if(spaceDim==1)
4578 const double *coords=_coords->getConstPointer();
4579 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4582 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4585 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4589 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4590 * least two its edges intersect each other anywhere except their extremities. An
4591 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4592 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4593 * cleared before filling in.
4594 * \param [in] eps - precision.
4595 * \throw If \a this->getMeshDimension() != 2.
4596 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4598 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4600 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4601 if(getMeshDimension()!=2)
4602 throw INTERP_KERNEL::Exception(msg);
4603 int spaceDim=getSpaceDimension();
4604 if(spaceDim!=2 && spaceDim!=3)
4605 throw INTERP_KERNEL::Exception(msg);
4606 const int *conn=_nodal_connec->getConstPointer();
4607 const int *connI=_nodal_connec_index->getConstPointer();
4608 int nbOfCells=getNumberOfCells();
4609 std::vector<double> cell2DinS2;
4610 for(int i=0;i<nbOfCells;i++)
4612 int offset=connI[i];
4613 int nbOfNodesForCell=connI[i+1]-offset-1;
4614 if(nbOfNodesForCell<=3)
4616 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4617 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4618 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4625 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4627 * 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.
4628 * 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.
4630 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4631 * This convex envelop is computed using Jarvis march algorithm.
4632 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4633 * 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)
4634 * 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.
4636 * @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.
4638 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4640 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4641 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4642 checkFullyDefined();
4643 const double *coords=getCoords()->getConstPointer();
4644 int nbOfCells=getNumberOfCells();
4645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4646 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4648 int *workIndexOut=nodalConnecIndexOut->getPointer();
4650 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4651 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4652 std::set<INTERP_KERNEL::NormalizedCellType> types;
4653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4654 isChanged->alloc(0,1);
4655 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4657 int pos=nodalConnecOut->getNumberOfTuples();
4658 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4659 isChanged->pushBackSilent(i);
4660 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4661 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4663 if(isChanged->empty())
4665 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4667 return isChanged.retn();
4671 * This method is \b NOT const because it can modify 'this'.
4672 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4673 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4674 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4675 * \b 1 for translation and rotation around point of 'mesh1D'.
4676 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
4678 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4680 checkFullyDefined();
4681 mesh1D->checkFullyDefined();
4682 if(!mesh1D->isContiguous1D())
4683 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4684 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4685 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4686 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4687 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4688 if(mesh1D->getMeshDimension()!=1)
4689 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4691 if(isPresenceOfQuadratic())
4693 if(mesh1D->isFullyQuadratic())
4696 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4699 int oldNbOfNodes=getNumberOfNodes();
4700 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4705 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4710 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4714 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4716 setCoords(newCoords);
4717 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4723 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4724 * If it is not the case an exception will be thrown.
4725 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4726 * intersection of plane defined by ('origin','vec').
4727 * This method has one in/out parameter : 'cut3DCurve'.
4728 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4729 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4730 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4731 * This method will throw an exception if 'this' contains a non linear segment.
4733 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4735 checkFullyDefined();
4736 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4737 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4738 int ncells=getNumberOfCells();
4739 int nnodes=getNumberOfNodes();
4740 double vec2[3],vec3[3],vec4[3];
4741 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4743 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4744 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4745 const int *conn=_nodal_connec->getConstPointer();
4746 const int *connI=_nodal_connec_index->getConstPointer();
4747 const double *coo=_coords->getConstPointer();
4748 std::vector<double> addCoo;
4749 for(int i=0;i<ncells;i++)
4751 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4753 if(cut3DCurve[i]==-2)
4755 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4756 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];
4757 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4758 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4759 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4761 const double *st2=coo+3*st;
4762 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4763 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]));
4764 if(pos>eps && pos<1-eps)
4766 int nNode=((int)addCoo.size())/3;
4767 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4768 addCoo.insert(addCoo.end(),vec4,vec4+3);
4769 cut3DCurve[i]=nnodes+nNode;
4775 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4779 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4780 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4781 coo2->alloc(newNbOfNodes,3);
4782 double *tmp=coo2->getPointer();
4783 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4784 std::copy(addCoo.begin(),addCoo.end(),tmp);
4785 DataArrayDouble::SetArrayIn(coo2,_coords);
4790 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4791 * @param mesh1D is the input 1D mesh used for translation computation.
4792 * @return newCoords new coords filled by this method.
4794 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4796 int oldNbOfNodes=getNumberOfNodes();
4797 int nbOf1DCells=mesh1D->getNumberOfCells();
4798 int spaceDim=getSpaceDimension();
4799 DataArrayDouble *ret=DataArrayDouble::New();
4800 std::vector<bool> isQuads;
4801 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4802 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4803 double *retPtr=ret->getPointer();
4804 const double *coords=getCoords()->getConstPointer();
4805 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4807 std::vector<double> c;
4811 for(int i=0;i<nbOf1DCells;i++)
4814 mesh1D->getNodeIdsOfCell(i,v);
4816 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4817 mesh1D->getCoordinatesOfNode(v[0],c);
4818 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4819 for(int j=0;j<oldNbOfNodes;j++)
4820 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4824 mesh1D->getCoordinatesOfNode(v[1],c);
4825 mesh1D->getCoordinatesOfNode(v[0],c);
4826 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4827 for(int j=0;j<oldNbOfNodes;j++)
4828 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4831 ret->copyStringInfoFrom(*getCoords());
4836 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4837 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4838 * @return newCoords new coords filled by this method.
4840 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4842 if(mesh1D->getSpaceDimension()==2)
4843 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4844 if(mesh1D->getSpaceDimension()==3)
4845 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4846 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4850 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4851 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4852 * @return newCoords new coords filled by this method.
4854 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4858 int oldNbOfNodes=getNumberOfNodes();
4859 int nbOf1DCells=mesh1D->getNumberOfCells();
4861 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4862 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4863 int nbOfLevsInVec=nbOf1DCells+1;
4864 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4865 double *retPtr=ret->getPointer();
4866 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4867 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4868 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4869 tmp->setCoords(tmp2);
4870 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4871 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4872 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4873 for(int i=1;i<nbOfLevsInVec;i++)
4875 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4876 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4877 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4878 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4879 tmp->translate(vec);
4880 double tmp3[2],radius,alpha,alpha0;
4881 const double *p0=i+1<nbOfLevsInVec?begin:third;
4882 const double *p1=i+1<nbOfLevsInVec?end:begin;
4883 const double *p2=i+1<nbOfLevsInVec?third:end;
4884 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4885 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]);
4886 double angle=acos(cosangle/(radius*radius));
4887 tmp->rotate(end,0,angle);
4888 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4894 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4895 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4896 * @return newCoords new coords filled by this method.
4898 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4902 int oldNbOfNodes=getNumberOfNodes();
4903 int nbOf1DCells=mesh1D->getNumberOfCells();
4905 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4907 int nbOfLevsInVec=nbOf1DCells+1;
4908 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4909 double *retPtr=ret->getPointer();
4910 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4911 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4912 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4913 tmp->setCoords(tmp2);
4914 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4915 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4916 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4917 for(int i=1;i<nbOfLevsInVec;i++)
4919 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4920 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4921 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4922 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4923 tmp->translate(vec);
4924 double tmp3[2],radius,alpha,alpha0;
4925 const double *p0=i+1<nbOfLevsInVec?begin:third;
4926 const double *p1=i+1<nbOfLevsInVec?end:begin;
4927 const double *p2=i+1<nbOfLevsInVec?third:end;
4928 double vecPlane[3]={
4929 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4930 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4931 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4933 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4936 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4937 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4938 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4940 double c2=cos(asin(s2));
4942 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4943 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4944 {-vec2[1]*s2, vec2[0]*s2, c2}
4946 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]};
4947 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]};
4948 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]};
4949 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4950 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]);
4951 double angle=acos(cosangle/(radius*radius));
4952 tmp->rotate(end,vecPlane,angle);
4955 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4961 * This method is private because not easy to use for end user. This method is const contrary to
4962 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4963 * the coords sorted slice by slice.
4964 * @param isQuad specifies presence of quadratic cells.
4966 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4968 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4969 int nbOf2DCells=getNumberOfCells();
4970 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4971 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4972 const int *conn=_nodal_connec->getConstPointer();
4973 const int *connI=_nodal_connec_index->getConstPointer();
4974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4976 newConnI->alloc(nbOf3DCells+1,1);
4977 int *newConnIPtr=newConnI->getPointer();
4979 std::vector<int> newc;
4980 for(int j=0;j<nbOf2DCells;j++)
4982 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4983 *newConnIPtr++=(int)newc.size();
4985 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4986 int *newConnPtr=newConn->getPointer();
4987 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4988 newConnIPtr=newConnI->getPointer();
4989 for(int iz=0;iz<nbOf1DCells;iz++)
4992 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4993 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4995 int icell=(int)(iter-newc.begin());
4996 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4999 *newConnPtr=(*iter)+iz*deltaPerLev;
5004 *newConnPtr=(*iter);
5007 ret->setConnectivity(newConn,newConnI,true);
5008 ret->setCoords(getCoords());
5013 * Checks if \a this mesh is constituted by only quadratic cells.
5014 * \return bool - \c true if there are only quadratic cells in \a this mesh.
5015 * \throw If the coordinates array is not set.
5016 * \throw If the nodal connectivity of cells is not defined.
5018 bool MEDCouplingUMesh::isFullyQuadratic() const
5020 checkFullyDefined();
5022 int nbOfCells=getNumberOfCells();
5023 for(int i=0;i<nbOfCells && ret;i++)
5025 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5026 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5027 ret=cm.isQuadratic();
5033 * Checks if \a this mesh includes any quadratic cell.
5034 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5035 * \throw If the coordinates array is not set.
5036 * \throw If the nodal connectivity of cells is not defined.
5038 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5040 checkFullyDefined();
5042 int nbOfCells=getNumberOfCells();
5043 for(int i=0;i<nbOfCells && !ret;i++)
5045 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5046 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5047 ret=cm.isQuadratic();
5053 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5054 * this mesh, it remains unchanged.
5055 * \throw If the coordinates array is not set.
5056 * \throw If the nodal connectivity of cells is not defined.
5058 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
5060 checkFullyDefined();
5061 int nbOfCells=getNumberOfCells();
5063 const int *iciptr=_nodal_connec_index->getConstPointer();
5064 for(int i=0;i<nbOfCells;i++)
5066 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5067 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5068 if(cm.isQuadratic())
5070 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5071 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5072 if(!cml.isDynamic())
5073 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5075 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5080 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5082 const int *icptr=_nodal_connec->getConstPointer();
5083 newConn->alloc(getMeshLength()-delta,1);
5084 newConnI->alloc(nbOfCells+1,1);
5085 int *ocptr=newConn->getPointer();
5086 int *ociptr=newConnI->getPointer();
5089 for(int i=0;i<nbOfCells;i++,ociptr++)
5091 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5092 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5093 if(!cm.isQuadratic())
5095 _types.insert(type);
5096 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5097 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5101 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5102 _types.insert(typel);
5103 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5104 int newNbOfNodes=cml.getNumberOfNodes();
5106 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5107 *ocptr++=(int)typel;
5108 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5109 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5112 setConnectivity(newConn,newConnI,false);
5116 * This method converts all linear cell in \a this to quadratic one.
5117 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5118 * 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)
5119 * 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.
5120 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5121 * end of the existing coordinates.
5123 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5124 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5125 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5127 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5129 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5131 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
5133 DataArrayInt *conn=0,*connI=0;
5134 DataArrayDouble *coords=0;
5135 std::set<INTERP_KERNEL::NormalizedCellType> types;
5136 checkFullyDefined();
5137 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5138 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5139 int meshDim=getMeshDimension();
5140 switch(conversionType)
5146 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5147 connSafe=conn; connISafe=connI; coordsSafe=coords;
5150 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5151 connSafe=conn; connISafe=connI; coordsSafe=coords;
5154 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5155 connSafe=conn; connISafe=connI; coordsSafe=coords;
5158 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5166 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5167 connSafe=conn; connISafe=connI; coordsSafe=coords;
5170 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5171 connSafe=conn; connISafe=connI; coordsSafe=coords;
5174 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5175 connSafe=conn; connISafe=connI; coordsSafe=coords;
5178 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5183 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5185 setConnectivity(connSafe,connISafe,false);
5187 setCoords(coordsSafe);
5192 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5193 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5194 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5196 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5198 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5202 int nbOfCells=getNumberOfCells();
5203 int nbOfNodes=getNumberOfNodes();
5204 const int *cPtr=_nodal_connec->getConstPointer();
5205 const int *icPtr=_nodal_connec_index->getConstPointer();
5206 int lastVal=0,offset=nbOfNodes;
5207 for(int i=0;i<nbOfCells;i++,icPtr++)
5209 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5210 if(type==INTERP_KERNEL::NORM_SEG2)
5212 types.insert(INTERP_KERNEL::NORM_SEG3);
5213 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5214 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5215 newConn->pushBackSilent(offset++);
5217 newConnI->pushBackSilent(lastVal);
5218 ret->pushBackSilent(i);
5223 lastVal+=(icPtr[1]-icPtr[0]);
5224 newConnI->pushBackSilent(lastVal);
5225 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5228 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5229 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5233 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)
5235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5239 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5240 DataArrayInt *conn1D=0,*conn1DI=0;
5241 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5242 DataArrayDouble *coordsTmp=0;
5243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5244 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5246 const int *c1DPtr=conn1D->begin();
5247 const int *c1DIPtr=conn1DI->begin();
5248 int nbOfCells=getNumberOfCells();
5249 const int *cPtr=_nodal_connec->getConstPointer();
5250 const int *icPtr=_nodal_connec_index->getConstPointer();
5252 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5254 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5255 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5256 if(!cm.isQuadratic())
5258 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5259 types.insert(typ2); newConn->pushBackSilent(typ2);
5260 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5261 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5262 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5263 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5264 newConnI->pushBackSilent(lastVal);
5265 ret->pushBackSilent(i);
5270 lastVal+=(icPtr[1]-icPtr[0]);
5271 newConnI->pushBackSilent(lastVal);
5272 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5275 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5280 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5281 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5282 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5284 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5288 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5289 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5292 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5301 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5302 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5303 DataArrayInt *conn1D=0,*conn1DI=0;
5304 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5305 DataArrayDouble *coordsTmp=0;
5306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5307 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5309 const int *c1DPtr=conn1D->begin();
5310 const int *c1DIPtr=conn1DI->begin();
5311 int nbOfCells=getNumberOfCells();
5312 const int *cPtr=_nodal_connec->getConstPointer();
5313 const int *icPtr=_nodal_connec_index->getConstPointer();
5314 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5315 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5317 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5318 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5319 if(!cm.isQuadratic())
5321 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5322 types.insert(typ2); newConn->pushBackSilent(typ2);
5323 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5324 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5325 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5326 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5327 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5328 newConnI->pushBackSilent(lastVal);
5329 ret->pushBackSilent(i);
5334 lastVal+=(icPtr[1]-icPtr[0]);
5335 newConnI->pushBackSilent(lastVal);
5336 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5339 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5340 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5345 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5346 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5347 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5349 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5352 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5353 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5356 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5359 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5361 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5367 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5368 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5369 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5370 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5371 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5374 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5376 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5378 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5379 int nbOfCells=getNumberOfCells();
5380 const int *cPtr=_nodal_connec->getConstPointer();
5381 const int *icPtr=_nodal_connec_index->getConstPointer();
5382 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5383 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5385 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5386 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5387 if(!cm.isQuadratic())
5389 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5390 if(typ2==INTERP_KERNEL::NORM_ERROR)
5392 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5393 throw INTERP_KERNEL::Exception(oss.str().c_str());
5395 types.insert(typ2); newConn->pushBackSilent(typ2);
5396 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5397 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5398 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5399 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5401 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5402 int tmpPos=newConn->getNumberOfTuples();
5403 newConn->pushBackSilent(nodeId2);
5404 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5406 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5407 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5408 newConnI->pushBackSilent(lastVal);
5409 ret->pushBackSilent(i);
5414 lastVal+=(icPtr[1]-icPtr[0]);
5415 newConnI->pushBackSilent(lastVal);
5416 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5421 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5422 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5423 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5424 int *c=newConn->getPointer();
5425 const int *cI(newConnI->begin());
5426 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5427 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5428 offset=coordsTmp2Safe->getNumberOfTuples();
5429 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5430 c[cI[(*elt)+1]-1]+=offset;
5431 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5436 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5437 * so that the number of cells remains the same. Quadratic faces are converted to
5438 * polygons. This method works only for 2D meshes in
5439 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5440 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5441 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5442 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5443 * a polylinized edge constituting the input polygon.
5444 * \throw If the coordinates array is not set.
5445 * \throw If the nodal connectivity of cells is not defined.
5446 * \throw If \a this->getMeshDimension() != 2.
5447 * \throw If \a this->getSpaceDimension() != 2.
5449 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5451 checkFullyDefined();
5452 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5454 double epsa=fabs(eps);
5455 if(epsa<std::numeric_limits<double>::min())
5456 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 !");
5457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5462 revDesc1=0; revDescIndx1=0;
5463 mDesc->tessellate2DCurve(eps);
5464 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5465 setCoords(mDesc->getCoords());
5469 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5470 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5471 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5472 * a sub-divided edge.
5473 * \throw If the coordinates array is not set.
5474 * \throw If the nodal connectivity of cells is not defined.
5475 * \throw If \a this->getMeshDimension() != 1.
5476 * \throw If \a this->getSpaceDimension() != 2.
5478 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5480 checkFullyDefined();
5481 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5482 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5483 double epsa=fabs(eps);
5484 if(epsa<std::numeric_limits<double>::min())
5485 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 !");
5486 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5487 int nbCells=getNumberOfCells();
5488 int nbNodes=getNumberOfNodes();
5489 const int *conn=_nodal_connec->getConstPointer();
5490 const int *connI=_nodal_connec_index->getConstPointer();
5491 const double *coords=_coords->getConstPointer();
5492 std::vector<double> addCoo;
5493 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5494 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5495 newConnI->alloc(nbCells+1,1);
5496 int *newConnIPtr=newConnI->getPointer();
5499 INTERP_KERNEL::Node *tmp2[3];
5500 std::set<INTERP_KERNEL::NormalizedCellType> types;
5501 for(int i=0;i<nbCells;i++,newConnIPtr++)
5503 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5504 if(cm.isQuadratic())
5505 {//assert(connI[i+1]-connI[i]-1==3)
5506 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5507 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5508 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5509 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5510 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5513 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5514 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5516 newConnIPtr[1]=(int)newConn.size();
5520 types.insert(INTERP_KERNEL::NORM_SEG2);
5521 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5522 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5523 newConnIPtr[1]=newConnIPtr[0]+3;
5528 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5529 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5530 newConnIPtr[1]=newConnIPtr[0]+3;
5533 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5536 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5538 newConnArr->alloc((int)newConn.size(),1);
5539 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5540 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5541 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5542 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5543 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5544 std::copy(addCoo.begin(),addCoo.end(),work);
5545 DataArrayDouble::SetArrayIn(newCoords,_coords);
5550 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5551 * In addition, returns an array mapping new cells to old ones. <br>
5552 * This method typically increases the number of cells in \a this mesh
5553 * but the number of nodes remains \b unchanged.
5554 * That's why the 3D splitting policies
5555 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5556 * \param [in] policy - specifies a pattern used for splitting.
5557 * The semantic of \a policy is:
5558 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5559 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5560 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5561 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5562 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5563 * an id of old cell producing it. The caller is to delete this array using
5564 * decrRef() as it is no more needed.
5565 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5566 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5567 * and \a this->getMeshDimension() != 3.
5568 * \throw If \a policy is not one of the four discussed above.
5569 * \throw If the nodal connectivity of cells is not defined.
5571 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5576 return simplexizePol0();
5578 return simplexizePol1();
5579 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5580 return simplexizePlanarFace5();
5581 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5582 return simplexizePlanarFace6();
5584 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)");
5589 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5590 * - 1D: INTERP_KERNEL::NORM_SEG2
5591 * - 2D: INTERP_KERNEL::NORM_TRI3
5592 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5594 * This method is useful for users that need to use P1 field services as
5595 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5596 * All these methods need mesh support containing only simplex cells.
5597 * \return bool - \c true if there are only simplex cells in \a this mesh.
5598 * \throw If the coordinates array is not set.
5599 * \throw If the nodal connectivity of cells is not defined.
5600 * \throw If \a this->getMeshDimension() < 1.
5602 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5604 checkFullyDefined();
5605 int mdim=getMeshDimension();
5606 if(mdim<1 || mdim>3)
5607 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5608 int nbCells=getNumberOfCells();
5609 const int *conn=_nodal_connec->getConstPointer();
5610 const int *connI=_nodal_connec_index->getConstPointer();
5611 for(int i=0;i<nbCells;i++)
5613 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5621 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5623 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5625 checkConnectivityFullyDefined();
5626 if(getMeshDimension()!=2)
5627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5628 int nbOfCells=getNumberOfCells();
5629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5630 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5631 ret->alloc(nbOfCells+nbOfCutCells,1);
5632 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5633 int *retPt=ret->getPointer();
5634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5635 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5636 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5637 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5638 int *pt=newConn->getPointer();
5639 int *ptI=newConnI->getPointer();
5641 const int *oldc=_nodal_connec->getConstPointer();
5642 const int *ci=_nodal_connec_index->getConstPointer();
5643 for(int i=0;i<nbOfCells;i++,ci++)
5645 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5647 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5648 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5649 pt=std::copy(tmp,tmp+8,pt);
5658 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5659 ptI[1]=ptI[0]+ci[1]-ci[0];
5664 _nodal_connec->decrRef();
5665 _nodal_connec=newConn.retn();
5666 _nodal_connec_index->decrRef();
5667 _nodal_connec_index=newConnI.retn();
5674 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5676 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5678 checkConnectivityFullyDefined();
5679 if(getMeshDimension()!=2)
5680 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5681 int nbOfCells=getNumberOfCells();
5682 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5683 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5684 ret->alloc(nbOfCells+nbOfCutCells,1);
5685 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5686 int *retPt=ret->getPointer();
5687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5689 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5690 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5691 int *pt=newConn->getPointer();
5692 int *ptI=newConnI->getPointer();
5694 const int *oldc=_nodal_connec->getConstPointer();
5695 const int *ci=_nodal_connec_index->getConstPointer();
5696 for(int i=0;i<nbOfCells;i++,ci++)
5698 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5700 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5701 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5702 pt=std::copy(tmp,tmp+8,pt);
5711 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5712 ptI[1]=ptI[0]+ci[1]-ci[0];
5717 _nodal_connec->decrRef();
5718 _nodal_connec=newConn.retn();
5719 _nodal_connec_index->decrRef();
5720 _nodal_connec_index=newConnI.retn();
5727 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5729 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5731 checkConnectivityFullyDefined();
5732 if(getMeshDimension()!=3)
5733 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5734 int nbOfCells=getNumberOfCells();
5735 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5736 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5737 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5738 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5739 int *retPt=ret->getPointer();
5740 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5742 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5743 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5744 int *pt=newConn->getPointer();
5745 int *ptI=newConnI->getPointer();
5747 const int *oldc=_nodal_connec->getConstPointer();
5748 const int *ci=_nodal_connec_index->getConstPointer();
5749 for(int i=0;i<nbOfCells;i++,ci++)
5751 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5753 for(int j=0;j<5;j++,pt+=5,ptI++)
5755 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5756 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];
5763 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5764 ptI[1]=ptI[0]+ci[1]-ci[0];
5769 _nodal_connec->decrRef();
5770 _nodal_connec=newConn.retn();
5771 _nodal_connec_index->decrRef();
5772 _nodal_connec_index=newConnI.retn();
5779 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5781 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5783 checkConnectivityFullyDefined();
5784 if(getMeshDimension()!=3)
5785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5786 int nbOfCells=getNumberOfCells();
5787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5788 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5789 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5790 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5791 int *retPt=ret->getPointer();
5792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5794 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5795 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5796 int *pt=newConn->getPointer();
5797 int *ptI=newConnI->getPointer();
5799 const int *oldc=_nodal_connec->getConstPointer();
5800 const int *ci=_nodal_connec_index->getConstPointer();
5801 for(int i=0;i<nbOfCells;i++,ci++)
5803 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5805 for(int j=0;j<6;j++,pt+=5,ptI++)
5807 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5808 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];
5815 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5816 ptI[1]=ptI[0]+ci[1]-ci[0];
5821 _nodal_connec->decrRef();
5822 _nodal_connec=newConn.retn();
5823 _nodal_connec_index->decrRef();
5824 _nodal_connec_index=newConnI.retn();
5831 * 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.
5832 * This method completly ignore coordinates.
5833 * @param nodeSubdived is the nodal connectivity of subdivision of edges
5834 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5835 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5836 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5838 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5840 checkFullyDefined();
5841 if(getMeshDimension()!=2)
5842 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5843 int nbOfCells=getNumberOfCells();
5844 int *connI=_nodal_connec_index->getPointer();
5846 for(int i=0;i<nbOfCells;i++,connI++)
5848 int offset=descIndex[i];
5849 int nbOfEdges=descIndex[i+1]-offset;
5851 bool ddirect=desc[offset+nbOfEdges-1]>0;
5852 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5853 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5854 for(int j=0;j<nbOfEdges;j++)
5856 bool direct=desc[offset+j]>0;
5857 int edgeId=std::abs(desc[offset+j])-1;
5858 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5860 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5861 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5862 int ref2=direct?id1:id2;
5865 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5866 newConnLgth+=nbOfSubNodes-1;
5871 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5872 throw INTERP_KERNEL::Exception(oss.str().c_str());
5877 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5880 newConnLgth++;//+1 is for cell type
5881 connI[1]=newConnLgth;
5884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5885 newConn->alloc(newConnLgth,1);
5886 int *work=newConn->getPointer();
5887 for(int i=0;i<nbOfCells;i++)
5889 *work++=INTERP_KERNEL::NORM_POLYGON;
5890 int offset=descIndex[i];
5891 int nbOfEdges=descIndex[i+1]-offset;
5892 for(int j=0;j<nbOfEdges;j++)
5894 bool direct=desc[offset+j]>0;
5895 int edgeId=std::abs(desc[offset+j])-1;
5897 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5900 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5901 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5902 work=std::copy(it,it+nbOfSubNodes-1,work);
5906 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5909 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5913 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5914 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5915 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5916 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5917 * so it can be useful to call mergeNodes() before calling this method.
5918 * \throw If \a this->getMeshDimension() <= 1.
5919 * \throw If the coordinates array is not set.
5920 * \throw If the nodal connectivity of cells is not defined.
5922 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5924 checkFullyDefined();
5925 if(getMeshDimension()<=1)
5926 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5927 int nbOfCells=getNumberOfCells();
5930 int initMeshLgth=getMeshLength();
5931 int *conn=_nodal_connec->getPointer();
5932 int *index=_nodal_connec_index->getPointer();
5936 for(int i=0;i<nbOfCells;i++)
5938 lgthOfCurCell=index[i+1]-posOfCurCell;
5939 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5941 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5942 conn+newPos+1,newLgth);
5943 conn[newPos]=newType;
5945 posOfCurCell=index[i+1];
5948 if(newPos!=initMeshLgth)
5949 _nodal_connec->reAlloc(newPos);
5954 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5955 * A cell is considered to be oriented correctly if an angle between its
5956 * normal vector and a given vector is less than \c PI / \c 2.
5957 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5959 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5961 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5962 * is not cleared before filling in.
5963 * \throw If \a this->getMeshDimension() != 2.
5964 * \throw If \a this->getSpaceDimension() != 3.
5966 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5967 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5969 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5971 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5972 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5973 int nbOfCells=getNumberOfCells();
5974 const int *conn=_nodal_connec->getConstPointer();
5975 const int *connI=_nodal_connec_index->getConstPointer();
5976 const double *coordsPtr=_coords->getConstPointer();
5977 for(int i=0;i<nbOfCells;i++)
5979 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5980 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5982 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5983 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5990 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5991 * considered to be oriented correctly if an angle between its normal vector and a
5992 * given vector is less than \c PI / \c 2.
5993 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5995 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5997 * \throw If \a this->getMeshDimension() != 2.
5998 * \throw If \a this->getSpaceDimension() != 3.
6000 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6001 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6003 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
6005 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6006 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6007 int nbOfCells=getNumberOfCells();
6008 int *conn=_nodal_connec->getPointer();
6009 const int *connI=_nodal_connec_index->getConstPointer();
6010 const double *coordsPtr=_coords->getConstPointer();
6011 bool isModified=false;
6012 for(int i=0;i<nbOfCells;i++)
6014 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6015 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6017 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6018 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6021 std::vector<int> tmp(connI[i+1]-connI[i]-2);
6022 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
6023 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
6028 _nodal_connec->declareAsNew();
6033 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6034 * oriented facets. The normal vector of the facet should point out of the cell.
6035 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6036 * is not cleared before filling in.
6037 * \throw If \a this->getMeshDimension() != 3.
6038 * \throw If \a this->getSpaceDimension() != 3.
6039 * \throw If the coordinates array is not set.
6040 * \throw If the nodal connectivity of cells is not defined.
6042 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6043 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6045 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
6047 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6048 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6049 int nbOfCells=getNumberOfCells();
6050 const int *conn=_nodal_connec->getConstPointer();
6051 const int *connI=_nodal_connec_index->getConstPointer();
6052 const double *coordsPtr=_coords->getConstPointer();
6053 for(int i=0;i<nbOfCells;i++)
6055 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6056 if(type==INTERP_KERNEL::NORM_POLYHED)
6058 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6065 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6067 * \throw If \a this->getMeshDimension() != 3.
6068 * \throw If \a this->getSpaceDimension() != 3.
6069 * \throw If the coordinates array is not set.
6070 * \throw If the nodal connectivity of cells is not defined.
6071 * \throw If the reparation fails.
6073 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6074 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6075 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6077 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
6079 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6080 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6081 int nbOfCells=getNumberOfCells();
6082 int *conn=_nodal_connec->getPointer();
6083 const int *connI=_nodal_connec_index->getConstPointer();
6084 const double *coordsPtr=_coords->getConstPointer();
6085 for(int i=0;i<nbOfCells;i++)
6087 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6088 if(type==INTERP_KERNEL::NORM_POLYHED)
6092 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6093 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6095 catch(INTERP_KERNEL::Exception& e)
6097 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6098 throw INTERP_KERNEL::Exception(oss.str().c_str());
6106 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6107 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6108 * according to which the first facet of the cell should be oriented to have the normal vector
6109 * pointing out of cell.
6110 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6111 * cells. The caller is to delete this array using decrRef() as it is no more
6113 * \throw If \a this->getMeshDimension() != 3.
6114 * \throw If \a this->getSpaceDimension() != 3.
6115 * \throw If the coordinates array is not set.
6116 * \throw If the nodal connectivity of cells is not defined.
6118 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6119 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6120 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6122 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
6124 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6125 if(getMeshDimension()!=3)
6126 throw INTERP_KERNEL::Exception(msg);
6127 int spaceDim=getSpaceDimension();
6129 throw INTERP_KERNEL::Exception(msg);
6131 int nbOfCells=getNumberOfCells();
6132 int *conn=_nodal_connec->getPointer();
6133 const int *connI=_nodal_connec_index->getConstPointer();
6134 const double *coo=getCoords()->getConstPointer();
6135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6136 for(int i=0;i<nbOfCells;i++)
6138 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6139 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6141 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6143 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6144 cells->pushBackSilent(i);
6148 return cells.retn();
6152 * This method is a faster method to correct orientation of all 3D cells in \a this.
6153 * 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.
6154 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6156 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6157 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6159 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
6161 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6162 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6163 int nbOfCells=getNumberOfCells();
6164 int *conn=_nodal_connec->getPointer();
6165 const int *connI=_nodal_connec_index->getConstPointer();
6166 const double *coordsPtr=_coords->getConstPointer();
6167 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6168 for(int i=0;i<nbOfCells;i++)
6170 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6173 case INTERP_KERNEL::NORM_TETRA4:
6175 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6177 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6178 ret->pushBackSilent(i);
6182 case INTERP_KERNEL::NORM_PYRA5:
6184 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6186 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6187 ret->pushBackSilent(i);
6191 case INTERP_KERNEL::NORM_PENTA6:
6192 case INTERP_KERNEL::NORM_HEXA8:
6193 case INTERP_KERNEL::NORM_HEXGP12:
6195 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6197 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6198 ret->pushBackSilent(i);
6202 case INTERP_KERNEL::NORM_POLYHED:
6204 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6206 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6207 ret->pushBackSilent(i);
6212 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 !");
6220 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6221 * If it is not the case an exception will be thrown.
6222 * This method is fast because the first cell of 'this' is used to compute the plane.
6223 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6224 * @param pos output of size at least 3 used to store a point owned of searched plane.
6226 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
6228 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6229 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6230 const int *conn=_nodal_connec->getConstPointer();
6231 const int *connI=_nodal_connec_index->getConstPointer();
6232 const double *coordsPtr=_coords->getConstPointer();
6233 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6234 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6238 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6239 * cells. Currently cells of the following types are treated:
6240 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6241 * For a cell of other type an exception is thrown.
6242 * Space dimension of a 2D mesh can be either 2 or 3.
6243 * The Edge Ratio of a cell \f$t\f$ is:
6244 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6245 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6246 * the smallest edge lengths of \f$t\f$.
6247 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6248 * cells and one time, lying on \a this mesh. The caller is to delete this
6249 * field using decrRef() as it is no more needed.
6250 * \throw If the coordinates array is not set.
6251 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6252 * \throw If the connectivity data array has more than one component.
6253 * \throw If the connectivity data array has a named component.
6254 * \throw If the connectivity index data array has more than one component.
6255 * \throw If the connectivity index data array has a named component.
6256 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6257 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6258 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6260 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
6263 int spaceDim=getSpaceDimension();
6264 int meshDim=getMeshDimension();
6265 if(spaceDim!=2 && spaceDim!=3)
6266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6267 if(meshDim!=2 && meshDim!=3)
6268 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6269 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6271 int nbOfCells=getNumberOfCells();
6272 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6273 arr->alloc(nbOfCells,1);
6274 double *pt=arr->getPointer();
6275 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6276 const int *conn=_nodal_connec->getConstPointer();
6277 const int *connI=_nodal_connec_index->getConstPointer();
6278 const double *coo=_coords->getConstPointer();
6280 for(int i=0;i<nbOfCells;i++,pt++)
6282 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6285 case INTERP_KERNEL::NORM_TRI3:
6287 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6288 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6291 case INTERP_KERNEL::NORM_QUAD4:
6293 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6294 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6297 case INTERP_KERNEL::NORM_TETRA4:
6299 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6300 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6304 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6306 conn+=connI[i+1]-connI[i];
6308 ret->setName("EdgeRatio");
6309 ret->synchronizeTimeWithSupport();
6314 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6315 * cells. Currently cells of the following types are treated:
6316 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6317 * For a cell of other type an exception is thrown.
6318 * Space dimension of a 2D mesh can be either 2 or 3.
6319 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6320 * cells and one time, lying on \a this mesh. The caller is to delete this
6321 * field using decrRef() as it is no more needed.
6322 * \throw If the coordinates array is not set.
6323 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6324 * \throw If the connectivity data array has more than one component.
6325 * \throw If the connectivity data array has a named component.
6326 * \throw If the connectivity index data array has more than one component.
6327 * \throw If the connectivity index data array has a named component.
6328 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6329 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6330 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6332 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6335 int spaceDim=getSpaceDimension();
6336 int meshDim=getMeshDimension();
6337 if(spaceDim!=2 && spaceDim!=3)
6338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6339 if(meshDim!=2 && meshDim!=3)
6340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6341 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6343 int nbOfCells=getNumberOfCells();
6344 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6345 arr->alloc(nbOfCells,1);
6346 double *pt=arr->getPointer();
6347 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6348 const int *conn=_nodal_connec->getConstPointer();
6349 const int *connI=_nodal_connec_index->getConstPointer();
6350 const double *coo=_coords->getConstPointer();
6352 for(int i=0;i<nbOfCells;i++,pt++)
6354 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6357 case INTERP_KERNEL::NORM_TRI3:
6359 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6360 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6363 case INTERP_KERNEL::NORM_QUAD4:
6365 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6366 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6369 case INTERP_KERNEL::NORM_TETRA4:
6371 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6372 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6376 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6378 conn+=connI[i+1]-connI[i];
6380 ret->setName("AspectRatio");
6381 ret->synchronizeTimeWithSupport();
6386 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6387 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6388 * treated: INTERP_KERNEL::NORM_QUAD4.
6389 * For a cell of other type an exception is thrown.
6390 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6391 * cells and one time, lying on \a this mesh. The caller is to delete this
6392 * field using decrRef() as it is no more needed.
6393 * \throw If the coordinates array is not set.
6394 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6395 * \throw If the connectivity data array has more than one component.
6396 * \throw If the connectivity data array has a named component.
6397 * \throw If the connectivity index data array has more than one component.
6398 * \throw If the connectivity index data array has a named component.
6399 * \throw If \a this->getMeshDimension() != 2.
6400 * \throw If \a this->getSpaceDimension() != 3.
6401 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6403 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6406 int spaceDim=getSpaceDimension();
6407 int meshDim=getMeshDimension();
6409 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6411 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6412 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6414 int nbOfCells=getNumberOfCells();
6415 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6416 arr->alloc(nbOfCells,1);
6417 double *pt=arr->getPointer();
6418 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6419 const int *conn=_nodal_connec->getConstPointer();
6420 const int *connI=_nodal_connec_index->getConstPointer();
6421 const double *coo=_coords->getConstPointer();
6423 for(int i=0;i<nbOfCells;i++,pt++)
6425 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6428 case INTERP_KERNEL::NORM_QUAD4:
6430 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6431 *pt=INTERP_KERNEL::quadWarp(tmp);
6435 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6437 conn+=connI[i+1]-connI[i];
6439 ret->setName("Warp");
6440 ret->synchronizeTimeWithSupport();
6446 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6447 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6448 * treated: INTERP_KERNEL::NORM_QUAD4.
6449 * For a cell of other type an exception is thrown.
6450 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6451 * cells and one time, lying on \a this mesh. The caller is to delete this
6452 * field using decrRef() as it is no more needed.
6453 * \throw If the coordinates array is not set.
6454 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6455 * \throw If the connectivity data array has more than one component.
6456 * \throw If the connectivity data array has a named component.
6457 * \throw If the connectivity index data array has more than one component.
6458 * \throw If the connectivity index data array has a named component.
6459 * \throw If \a this->getMeshDimension() != 2.
6460 * \throw If \a this->getSpaceDimension() != 3.
6461 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6463 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6466 int spaceDim=getSpaceDimension();
6467 int meshDim=getMeshDimension();
6469 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6471 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6472 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6474 int nbOfCells=getNumberOfCells();
6475 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6476 arr->alloc(nbOfCells,1);
6477 double *pt=arr->getPointer();
6478 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6479 const int *conn=_nodal_connec->getConstPointer();
6480 const int *connI=_nodal_connec_index->getConstPointer();
6481 const double *coo=_coords->getConstPointer();
6483 for(int i=0;i<nbOfCells;i++,pt++)
6485 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6488 case INTERP_KERNEL::NORM_QUAD4:
6490 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6491 *pt=INTERP_KERNEL::quadSkew(tmp);
6495 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6497 conn+=connI[i+1]-connI[i];
6499 ret->setName("Skew");
6500 ret->synchronizeTimeWithSupport();
6505 * This method aggregate the bbox of each cell and put it into bbox parameter.
6506 * @param bbox out parameter of size 2*spacedim*nbOfcells.
6508 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6510 int spaceDim=getSpaceDimension();
6511 int nbOfCells=getNumberOfCells();
6512 bbox.resize(2*nbOfCells*spaceDim);
6513 for(int i=0;i<nbOfCells*spaceDim;i++)
6515 bbox[2*i]=std::numeric_limits<double>::max();
6516 bbox[2*i+1]=-std::numeric_limits<double>::max();
6518 const double *coordsPtr=_coords->getConstPointer();
6519 const int *conn=_nodal_connec->getConstPointer();
6520 const int *connI=_nodal_connec_index->getConstPointer();
6521 for(int i=0;i<nbOfCells;i++)
6523 int offset=connI[i]+1;
6524 int nbOfNodesForCell=connI[i+1]-offset;
6525 for(int j=0;j<nbOfNodesForCell;j++)
6527 int nodeId=conn[offset+j];
6529 for(int k=0;k<spaceDim;k++)
6531 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6532 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6540 namespace ParaMEDMEMImpl
6545 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6546 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6555 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6556 bool operator() (const int& pos) { return _conn[pos]==_val; }
6566 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
6567 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6568 * 'this' is composed in cell types.
6569 * The returned array is of size 3*n where n is the number of different types present in 'this'.
6570 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
6571 * This parameter is kept only for compatibility with other methode listed above.
6573 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6575 checkConnectivityFullyDefined();
6576 const int *conn=_nodal_connec->getConstPointer();
6577 const int *connI=_nodal_connec_index->getConstPointer();
6578 const int *work=connI;
6579 int nbOfCells=getNumberOfCells();
6580 std::size_t n=getAllTypes().size();
6581 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6582 std::set<INTERP_KERNEL::NormalizedCellType> types;
6583 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6585 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6586 if(types.find(typ)!=types.end())
6588 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6589 oss << " is not contiguous !";
6590 throw INTERP_KERNEL::Exception(oss.str().c_str());
6594 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6595 ret[3*i+1]=(int)std::distance(work,work2);
6602 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
6603 * only for types cell, type node is not managed.
6604 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
6605 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6606 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6607 * If 2 or more same geometric type is in 'code' and exception is thrown too.
6609 * This method firstly checks
6610 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6611 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6612 * an exception is thrown too.
6614 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
6615 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
6616 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6618 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6622 std::size_t sz=code.size();
6625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6626 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6628 for(std::size_t i=0;i<n;i++)
6629 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6631 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6633 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6634 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6637 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6638 if(idsPerType.empty())
6640 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6641 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6642 if(types.size()==_types.size())
6645 DataArrayInt *ret=DataArrayInt::New();
6647 int *retPtr=ret->getPointer();
6648 const int *connI=_nodal_connec_index->getConstPointer();
6649 const int *conn=_nodal_connec->getConstPointer();
6650 int nbOfCells=getNumberOfCells();
6653 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6655 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6656 int offset=(int)std::distance(connI,i);
6657 if(code[3*kk+2]==-1)
6659 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6660 std::size_t pos2=std::distance(i,j);
6661 for(std::size_t k=0;k<pos2;k++)
6662 *retPtr++=(int)k+offset;
6667 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6668 retPtr,std::bind2nd(std::plus<int>(),offset));
6675 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6676 * 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.
6677 * 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.
6678 * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
6680 * @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.
6681 * @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,
6682 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6683 * @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.
6684 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6685 * @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
6687 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6689 if(profile->getNumberOfComponents()!=1)
6690 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6691 checkConnectivityFullyDefined();
6692 const int *conn=_nodal_connec->getConstPointer();
6693 const int *connI=_nodal_connec_index->getConstPointer();
6694 int nbOfCells=getNumberOfCells();
6695 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6696 std::vector<int> typeRangeVals(1);
6697 for(const int *i=connI;i!=connI+nbOfCells;)
6699 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6700 if(std::find(types.begin(),types.end(),curType)!=types.end())
6702 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6704 types.push_back(curType);
6705 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6706 typeRangeVals.push_back((int)std::distance(connI,i));
6709 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6710 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6715 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6716 code.resize(3*nbOfCastsFinal);
6717 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6718 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6719 for(int i=0;i<nbOfCastsFinal;i++)
6721 int castId=castsPresent->getIJ(i,0);
6722 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6723 idsInPflPerType2.push_back(tmp3);
6724 code[3*i]=(int)types[castId];
6725 code[3*i+1]=tmp3->getNumberOfTuples();
6726 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6727 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6729 tmp4->copyStringInfoFrom(*profile);
6730 idsPerType2.push_back(tmp4);
6731 code[3*i+2]=(int)idsPerType2.size()-1;
6738 std::size_t sz2=idsInPflPerType2.size();
6739 idsInPflPerType.resize(sz2);
6740 for(std::size_t i=0;i<sz2;i++)
6742 DataArrayInt *locDa=idsInPflPerType2[i];
6744 idsInPflPerType[i]=locDa;
6746 std::size_t sz=idsPerType2.size();
6747 idsPerType.resize(sz);
6748 for(std::size_t i=0;i<sz;i++)
6750 DataArrayInt *locDa=idsPerType2[i];
6752 idsPerType[i]=locDa;
6757 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6758 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6759 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6760 * 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.
6762 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6764 checkFullyDefined();
6765 nM1LevMesh->checkFullyDefined();
6766 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6767 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6768 if(_coords!=nM1LevMesh->getCoords())
6769 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6770 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6771 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6772 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6774 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6775 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6776 tmp->setConnectivity(tmp0,tmp1);
6777 tmp->renumberCells(ret0->getConstPointer(),false);
6778 revDesc=tmp->getNodalConnectivity();
6779 revDescIndx=tmp->getNodalConnectivityIndex();
6780 DataArrayInt *ret=0;
6781 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6784 ret->getMaxValue(tmp2);
6786 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6787 throw INTERP_KERNEL::Exception(oss.str().c_str());
6792 revDescIndx->incrRef();
6795 meshnM1Old2New=ret0;
6800 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6801 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6802 * in "Old to New" mode.
6803 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6804 * this array using decrRef() as it is no more needed.
6805 * \throw If the nodal connectivity of cells is not defined.
6807 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6809 checkConnectivityFullyDefined();
6810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6811 renumberCells(ret->getConstPointer(),false);
6816 * This methods checks that cells are sorted by their types.
6817 * This method makes asumption (no check) that connectivity is correctly set before calling.
6819 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6821 checkFullyDefined();
6822 const int *conn=_nodal_connec->getConstPointer();
6823 const int *connI=_nodal_connec_index->getConstPointer();
6824 int nbOfCells=getNumberOfCells();
6825 std::set<INTERP_KERNEL::NormalizedCellType> types;
6826 for(const int *i=connI;i!=connI+nbOfCells;)
6828 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6829 if(types.find(curType)!=types.end())
6831 types.insert(curType);
6832 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6838 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6839 * The geometric type order is specified by MED file.
6841 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6843 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6845 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6849 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6850 * that the order is specified in array defined by [orderBg,orderEnd).
6851 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6852 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6854 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6856 checkFullyDefined();
6857 const int *conn=_nodal_connec->getConstPointer();
6858 const int *connI=_nodal_connec_index->getConstPointer();
6859 int nbOfCells=getNumberOfCells();
6863 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6864 for(const int *i=connI;i!=connI+nbOfCells;)
6866 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6867 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6868 if(isTypeExists!=orderEnd)
6870 int pos=(int)std::distance(orderBg,isTypeExists);
6874 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6878 if(sg.find(curType)==sg.end())
6880 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6891 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6892 * 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
6893 * 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'.
6895 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6897 checkConnectivityFullyDefined();
6898 int nbOfCells=getNumberOfCells();
6899 const int *conn=_nodal_connec->getConstPointer();
6900 const int *connI=_nodal_connec_index->getConstPointer();
6901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6903 tmpa->alloc(nbOfCells,1);
6904 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6905 tmpb->fillWithZero();
6906 int *tmp=tmpa->getPointer();
6907 int *tmp2=tmpb->getPointer();
6908 for(const int *i=connI;i!=connI+nbOfCells;i++)
6910 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6913 int pos=(int)std::distance(orderBg,where);
6915 tmp[std::distance(connI,i)]=pos;
6919 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6920 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6921 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6922 throw INTERP_KERNEL::Exception(oss.str().c_str());
6925 nbPerType=tmpb.retn();
6930 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6932 * \return a new object containing the old to new correspondance.
6934 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6936 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6938 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6942 * 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'.
6943 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6944 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6945 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6947 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6949 DataArrayInt *nbPerType=0;
6950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6951 nbPerType->decrRef();
6952 return tmpa->buildPermArrPerLevel();
6956 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6957 * The number of cells remains unchanged after the call of this method.
6958 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6959 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6961 * @return the array giving the correspondance old to new.
6963 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6965 checkFullyDefined();
6967 const int *conn=_nodal_connec->getConstPointer();
6968 const int *connI=_nodal_connec_index->getConstPointer();
6969 int nbOfCells=getNumberOfCells();
6970 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6971 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6972 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6974 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6975 types.push_back(curType);
6976 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6978 DataArrayInt *ret=DataArrayInt::New();
6979 ret->alloc(nbOfCells,1);
6980 int *retPtr=ret->getPointer();
6981 std::fill(retPtr,retPtr+nbOfCells,-1);
6983 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6985 for(const int *i=connI;i!=connI+nbOfCells;i++)
6986 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6987 retPtr[std::distance(connI,i)]=newCellId++;
6989 renumberCells(retPtr,false);
6994 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6995 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6996 * This method makes asumption that connectivity is correctly set before calling.
6998 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7000 checkFullyDefined();
7001 const int *conn=_nodal_connec->getConstPointer();
7002 const int *connI=_nodal_connec_index->getConstPointer();
7003 int nbOfCells=getNumberOfCells();
7004 std::vector<MEDCouplingUMesh *> ret;
7005 for(const int *i=connI;i!=connI+nbOfCells;)
7007 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7008 int beginCellId=(int)std::distance(connI,i);
7009 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7010 int endCellId=(int)std::distance(connI,i);
7011 int sz=endCellId-beginCellId;
7012 int *cells=new int[sz];
7013 for(int j=0;j<sz;j++)
7014 cells[j]=beginCellId+j;
7015 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7023 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7024 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7025 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7026 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7027 * are not used here to avoid the build of big permutation array.
7029 * \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
7030 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7031 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7032 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7033 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7034 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7035 * \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
7036 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7038 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7039 DataArrayInt *&szOfCellGrpOfSameType,
7040 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7042 std::vector<const MEDCouplingUMesh *> ms2;
7043 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7046 (*it)->checkConnectivityFullyDefined();
7050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7051 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7052 int meshDim=ms2[0]->getMeshDimension();
7053 std::vector<const MEDCouplingUMesh *> m1ssm;
7054 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7056 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7057 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7060 ret1->alloc(0,1); ret2->alloc(0,1);
7061 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7063 if(meshDim!=(*it)->getMeshDimension())
7064 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7065 if(refCoo!=(*it)->getCoords())
7066 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7067 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7068 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7069 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7070 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7072 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7073 m1ssmSingleAuto.push_back(singleCell);
7074 m1ssmSingle.push_back(singleCell);
7075 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7078 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7080 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7081 for(std::size_t i=0;i<m1ssm.size();i++)
7082 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7083 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7084 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7085 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7090 * This method returns a newly created DataArrayInt instance.
7091 * This method retrieves cell ids in [begin,end) that have the type 'type'.
7093 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
7095 checkFullyDefined();
7096 const int *conn=_nodal_connec->getConstPointer();
7097 const int *connIndex=_nodal_connec_index->getConstPointer();
7098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7099 for(const int *w=begin;w!=end;w++)
7100 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7101 ret->pushBackSilent(*w);
7106 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7107 * are in [0:getNumberOfCells())
7109 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
7111 checkFullyDefined();
7112 const int *conn=_nodal_connec->getConstPointer();
7113 const int *connI=_nodal_connec_index->getConstPointer();
7114 int nbOfCells=getNumberOfCells();
7115 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
7116 int *tmp=new int[nbOfCells];
7117 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7120 for(const int *i=connI;i!=connI+nbOfCells;i++)
7121 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7122 tmp[std::distance(connI,i)]=j++;
7124 DataArrayInt *ret=DataArrayInt::New();
7125 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7126 ret->copyStringInfoFrom(*da);
7127 int *retPtr=ret->getPointer();
7128 const int *daPtr=da->getConstPointer();
7129 int nbOfElems=da->getNbOfElems();
7130 for(int k=0;k<nbOfElems;k++)
7131 retPtr[k]=tmp[daPtr[k]];
7137 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7138 * This method \b works \b for mesh sorted by type.
7139 * cells whose ids is in 'idsPerGeoType' array.
7140 * This method conserves coords and name of mesh.
7142 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7144 std::vector<int> code=getDistributionOfTypes();
7145 std::size_t nOfTypesInThis=code.size()/3;
7146 int sz=0,szOfType=0;
7147 for(std::size_t i=0;i<nOfTypesInThis;i++)
7152 szOfType=code[3*i+1];
7154 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7155 if(*work<0 || *work>=szOfType)
7157 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7158 oss << ". It should be in [0," << szOfType << ") !";
7159 throw INTERP_KERNEL::Exception(oss.str().c_str());
7161 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7162 int *idsPtr=idsTokeep->getPointer();
7164 for(std::size_t i=0;i<nOfTypesInThis;i++)
7167 for(int j=0;j<code[3*i+1];j++)
7170 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7171 offset+=code[3*i+1];
7173 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7174 ret->copyTinyInfoFrom(this);
7179 * This method returns a vector of size 'this->getNumberOfCells()'.
7180 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
7182 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7184 int ncell=getNumberOfCells();
7185 std::vector<bool> ret(ncell);
7186 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7187 const int *c=getNodalConnectivity()->getConstPointer();
7188 for(int i=0;i<ncell;i++)
7190 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7191 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7192 ret[i]=cm.isQuadratic();
7198 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
7200 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7202 if(other->getType()!=UNSTRUCTURED)
7203 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7204 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7205 return MergeUMeshes(this,otherC);
7209 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7210 * computed by averaging coordinates of cell nodes, so this method is not a right
7211 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7212 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7213 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7214 * components. The caller is to delete this array using decrRef() as it is
7216 * \throw If the coordinates array is not set.
7217 * \throw If the nodal connectivity of cells is not defined.
7218 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7220 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7222 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7223 int spaceDim=getSpaceDimension();
7224 int nbOfCells=getNumberOfCells();
7225 ret->alloc(nbOfCells,spaceDim);
7226 ret->copyStringInfoFrom(*getCoords());
7227 double *ptToFill=ret->getPointer();
7228 const int *nodal=_nodal_connec->getConstPointer();
7229 const int *nodalI=_nodal_connec_index->getConstPointer();
7230 const double *coor=_coords->getConstPointer();
7231 for(int i=0;i<nbOfCells;i++)
7233 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7234 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7241 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7242 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7244 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7245 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7247 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7248 * \throw If \a this is not fully defined (coordinates and connectivity)
7249 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7251 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7253 checkFullyDefined();
7254 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7255 int spaceDim=getSpaceDimension();
7256 int nbOfCells=getNumberOfCells();
7257 int nbOfNodes=getNumberOfNodes();
7258 ret->alloc(nbOfCells,spaceDim);
7259 double *ptToFill=ret->getPointer();
7260 const int *nodal=_nodal_connec->getConstPointer();
7261 const int *nodalI=_nodal_connec_index->getConstPointer();
7262 const double *coor=_coords->getConstPointer();
7263 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7265 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7266 std::fill(ptToFill,ptToFill+spaceDim,0.);
7267 if(type!=INTERP_KERNEL::NORM_POLYHED)
7269 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7271 if(*conn>=0 && *conn<nbOfNodes)
7272 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7275 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7276 throw INTERP_KERNEL::Exception(oss.str().c_str());
7279 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7280 if(nbOfNodesInCell>0)
7281 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7284 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7285 throw INTERP_KERNEL::Exception(oss.str().c_str());
7290 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7292 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7294 if(*it>=0 && *it<nbOfNodes)
7295 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7298 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7299 throw INTERP_KERNEL::Exception(oss.str().c_str());
7303 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7306 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7307 throw INTERP_KERNEL::Exception(oss.str().c_str());
7315 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7316 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7317 * are specified via an array of cell ids.
7318 * \warning Validity of the specified cell ids is not checked!
7319 * Valid range is [ 0, \a this->getNumberOfCells() ).
7320 * \param [in] begin - an array of cell ids of interest.
7321 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7322 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7323 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7324 * caller is to delete this array using decrRef() as it is no more needed.
7325 * \throw If the coordinates array is not set.
7326 * \throw If the nodal connectivity of cells is not defined.
7328 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7329 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7331 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7333 DataArrayDouble *ret=DataArrayDouble::New();
7334 int spaceDim=getSpaceDimension();
7335 int nbOfTuple=(int)std::distance(begin,end);
7336 ret->alloc(nbOfTuple,spaceDim);
7337 double *ptToFill=ret->getPointer();
7338 double *tmp=new double[spaceDim];
7339 const int *nodal=_nodal_connec->getConstPointer();
7340 const int *nodalI=_nodal_connec_index->getConstPointer();
7341 const double *coor=_coords->getConstPointer();
7342 for(const int *w=begin;w!=end;w++)
7344 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7345 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7353 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7356 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7359 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7360 da->checkAllocated();
7361 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7363 int nbOfTuples=da->getNumberOfTuples();
7364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7366 c->alloc(2*nbOfTuples,1);
7367 cI->alloc(nbOfTuples+1,1);
7368 int *cp=c->getPointer();
7369 int *cip=cI->getPointer();
7371 for(int i=0;i<nbOfTuples;i++)
7373 *cp++=INTERP_KERNEL::NORM_POINT1;
7377 ret->setConnectivity(c,cI,true);
7381 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7382 * Cells and nodes of
7383 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7384 * \param [in] mesh1 - the first mesh.
7385 * \param [in] mesh2 - the second mesh.
7386 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7387 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7388 * is no more needed.
7389 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7390 * \throw If the coordinates array is not set in none of the meshes.
7391 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7392 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7394 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7396 std::vector<const MEDCouplingUMesh *> tmp(2);
7397 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7398 return MergeUMeshes(tmp);
7402 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7403 * Cells and nodes of
7404 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7405 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7406 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7407 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7408 * is no more needed.
7409 * \throw If \a a.size() == 0.
7410 * \throw If \a a[ *i* ] == NULL.
7411 * \throw If the coordinates array is not set in none of the meshes.
7412 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7413 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7415 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7417 std::size_t sz=a.size();
7419 return MergeUMeshesLL(a);
7420 for(std::size_t ii=0;ii<sz;ii++)
7423 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7424 throw INTERP_KERNEL::Exception(oss.str().c_str());
7426 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7427 std::vector< const MEDCouplingUMesh * > aa(sz);
7429 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7431 const MEDCouplingUMesh *cur=a[i];
7432 const DataArrayDouble *coo=cur->getCoords();
7434 spaceDim=coo->getNumberOfComponents();
7437 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7438 for(std::size_t i=0;i<sz;i++)
7440 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7443 return MergeUMeshesLL(aa);
7448 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7451 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7452 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7453 int meshDim=(*it)->getMeshDimension();
7454 int nbOfCells=(*it)->getNumberOfCells();
7455 int meshLgth=(*it++)->getMeshLength();
7456 for(;it!=a.end();it++)
7458 if(meshDim!=(*it)->getMeshDimension())
7459 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7460 nbOfCells+=(*it)->getNumberOfCells();
7461 meshLgth+=(*it)->getMeshLength();
7463 std::vector<const MEDCouplingPointSet *> aps(a.size());
7464 std::copy(a.begin(),a.end(),aps.begin());
7465 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7466 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7467 ret->setCoords(pts);
7468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7469 c->alloc(meshLgth,1);
7470 int *cPtr=c->getPointer();
7471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7472 cI->alloc(nbOfCells+1,1);
7473 int *cIPtr=cI->getPointer();
7477 for(it=a.begin();it!=a.end();it++)
7479 int curNbOfCell=(*it)->getNumberOfCells();
7480 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7481 const int *curC=(*it)->_nodal_connec->getConstPointer();
7482 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7483 for(int j=0;j<curNbOfCell;j++)
7485 const int *src=curC+curCI[j];
7487 for(;src!=curC+curCI[j+1];src++,cPtr++)
7495 offset+=curCI[curNbOfCell];
7496 offset2+=(*it)->getNumberOfNodes();
7499 ret->setConnectivity(c,cI,true);
7506 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7507 * dimension and sharing the node coordinates array.
7508 * All cells of the first mesh precede all cells of the second mesh
7509 * within the result mesh.
7510 * \param [in] mesh1 - the first mesh.
7511 * \param [in] mesh2 - the second mesh.
7512 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7513 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7514 * is no more needed.
7515 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7516 * \throw If the meshes do not share the node coordinates array.
7517 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7518 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7520 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7522 std::vector<const MEDCouplingUMesh *> tmp(2);
7523 tmp[0]=mesh1; tmp[1]=mesh2;
7524 return MergeUMeshesOnSameCoords(tmp);
7528 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7529 * dimension and sharing the node coordinates array.
7530 * All cells of the *i*-th mesh precede all cells of the
7531 * (*i*+1)-th mesh within the result mesh.
7532 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7533 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7534 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7535 * is no more needed.
7536 * \throw If \a a.size() == 0.
7537 * \throw If \a a[ *i* ] == NULL.
7538 * \throw If the meshes do not share the node coordinates array.
7539 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7540 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7542 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7545 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7546 for(std::size_t ii=0;ii<meshes.size();ii++)
7549 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7550 throw INTERP_KERNEL::Exception(oss.str().c_str());
7552 const DataArrayDouble *coords=meshes.front()->getCoords();
7553 int meshDim=meshes.front()->getMeshDimension();
7554 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7556 int meshIndexLgth=0;
7557 for(;iter!=meshes.end();iter++)
7559 if(coords!=(*iter)->getCoords())
7560 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7561 if(meshDim!=(*iter)->getMeshDimension())
7562 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7563 meshLgth+=(*iter)->getMeshLength();
7564 meshIndexLgth+=(*iter)->getNumberOfCells();
7566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7567 nodal->alloc(meshLgth,1);
7568 int *nodalPtr=nodal->getPointer();
7569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7570 nodalIndex->alloc(meshIndexLgth+1,1);
7571 int *nodalIndexPtr=nodalIndex->getPointer();
7573 for(iter=meshes.begin();iter!=meshes.end();iter++)
7575 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7576 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7577 int nbOfCells=(*iter)->getNumberOfCells();
7578 int meshLgth2=(*iter)->getMeshLength();
7579 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7580 if(iter!=meshes.begin())
7581 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7583 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7586 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7587 ret->setName("merge");
7588 ret->setMeshDimension(meshDim);
7589 ret->setConnectivity(nodal,nodalIndex,true);
7590 ret->setCoords(coords);
7595 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7596 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7597 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7598 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7599 * New" mode are returned for each input mesh.
7600 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7601 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7602 * valid values [0,1,2], see zipConnectivityTraducer().
7603 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7604 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7605 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7607 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7608 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7609 * is no more needed.
7610 * \throw If \a meshes.size() == 0.
7611 * \throw If \a meshes[ *i* ] == NULL.
7612 * \throw If the meshes do not share the node coordinates array.
7613 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7614 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7615 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7616 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7618 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7620 //All checks are delegated to MergeUMeshesOnSameCoords
7621 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7622 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7623 corr.resize(meshes.size());
7624 std::size_t nbOfMeshes=meshes.size();
7626 const int *o2nPtr=o2n->getConstPointer();
7627 for(std::size_t i=0;i<nbOfMeshes;i++)
7629 DataArrayInt *tmp=DataArrayInt::New();
7630 int curNbOfCells=meshes[i]->getNumberOfCells();
7631 tmp->alloc(curNbOfCells,1);
7632 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7633 offset+=curNbOfCells;
7634 tmp->setName(meshes[i]->getName());
7641 * Makes all given meshes share the nodal connectivity array. The common connectivity
7642 * array is created by concatenating the connectivity arrays of all given meshes. All
7643 * the given meshes must be of the same space dimension but dimension of cells **can
7644 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7645 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7646 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7647 * \param [in,out] meshes - a vector of meshes to update.
7648 * \throw If any of \a meshes is NULL.
7649 * \throw If the coordinates array is not set in any of \a meshes.
7650 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7651 * \throw If \a meshes are of different space dimension.
7653 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7655 std::size_t sz=meshes.size();
7658 std::vector< const DataArrayDouble * > coords(meshes.size());
7659 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7660 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7664 (*it)->checkConnectivityFullyDefined();
7665 const DataArrayDouble *coo=(*it)->getCoords();
7670 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7671 oss << " has no coordinate array defined !";
7672 throw INTERP_KERNEL::Exception(oss.str().c_str());
7677 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7678 oss << " is null !";
7679 throw INTERP_KERNEL::Exception(oss.str().c_str());
7682 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7683 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7684 int offset=(*it)->getNumberOfNodes();
7685 (*it++)->setCoords(res);
7686 for(;it!=meshes.end();it++)
7688 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7689 (*it)->setCoords(res);
7690 (*it)->shiftNodeNumbersInConn(offset);
7691 offset+=oldNumberOfNodes;
7696 * Merges nodes coincident with a given precision within all given meshes that share
7697 * the nodal connectivity array. The given meshes **can be of different** mesh
7698 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7699 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7700 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7701 * \param [in,out] meshes - a vector of meshes to update.
7702 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7703 * \throw If any of \a meshes is NULL.
7704 * \throw If the \a meshes do not share the same node coordinates array.
7705 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7707 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7711 std::set<const DataArrayDouble *> s;
7712 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7715 s.insert((*it)->getCoords());
7718 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 !";
7719 throw INTERP_KERNEL::Exception(oss.str().c_str());
7724 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 !";
7725 throw INTERP_KERNEL::Exception(oss.str().c_str());
7727 const DataArrayDouble *coo=*(s.begin());
7731 DataArrayInt *comm,*commI;
7732 coo->findCommonTuples(eps,-1,comm,commI);
7733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7734 int oldNbOfNodes=coo->getNumberOfTuples();
7736 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7737 if(oldNbOfNodes==newNbOfNodes)
7739 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7740 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7742 (*it)->renumberNodesInConn(o2n->getConstPointer());
7743 (*it)->setCoords(newCoords);
7748 * 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.
7749 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7750 * @param isQuad specifies the policy of connectivity.
7751 * @ret in/out parameter in which the result will be append
7753 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7755 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7756 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7757 ret.push_back(cm.getExtrudedType());
7758 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7761 case INTERP_KERNEL::NORM_POINT1:
7763 ret.push_back(connBg[1]);
7764 ret.push_back(connBg[1]+nbOfNodesPerLev);
7767 case INTERP_KERNEL::NORM_SEG2:
7769 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7770 ret.insert(ret.end(),conn,conn+4);
7773 case INTERP_KERNEL::NORM_SEG3:
7775 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7776 ret.insert(ret.end(),conn,conn+8);
7779 case INTERP_KERNEL::NORM_QUAD4:
7781 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7782 ret.insert(ret.end(),conn,conn+8);
7785 case INTERP_KERNEL::NORM_TRI3:
7787 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7788 ret.insert(ret.end(),conn,conn+6);
7791 case INTERP_KERNEL::NORM_TRI6:
7793 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,
7794 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7795 ret.insert(ret.end(),conn,conn+15);
7798 case INTERP_KERNEL::NORM_QUAD8:
7801 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7802 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7803 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7805 ret.insert(ret.end(),conn,conn+20);
7808 case INTERP_KERNEL::NORM_POLYGON:
7810 std::back_insert_iterator< std::vector<int> > ii(ret);
7811 std::copy(connBg+1,connEnd,ii);
7813 std::reverse_iterator<const int *> rConnBg(connEnd);
7814 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7815 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7816 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7817 for(std::size_t i=0;i<nbOfRadFaces;i++)
7820 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7821 std::copy(conn,conn+4,ii);
7826 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7831 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
7833 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7835 double v[3]={0.,0.,0.};
7836 std::size_t sz=std::distance(begin,end);
7839 for(std::size_t i=0;i<sz;i++)
7841 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];
7842 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7843 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7845 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7849 * The polyhedron is specfied by its connectivity nodes in [begin,end).
7851 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7853 std::vector<std::pair<int,int> > edges;
7854 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7855 const int *bgFace=begin;
7856 for(std::size_t i=0;i<nbOfFaces;i++)
7858 const int *endFace=std::find(bgFace+1,end,-1);
7859 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7860 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7862 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7863 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7865 edges.push_back(p1);
7869 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7873 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
7875 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7877 double vec0[3],vec1[3];
7878 std::size_t sz=std::distance(begin,end);
7880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7881 int nbOfNodes=(int)sz/2;
7882 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7883 const double *pt0=coords+3*begin[0];
7884 const double *pt1=coords+3*begin[nbOfNodes];
7885 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7886 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7889 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7891 std::size_t sz=std::distance(begin,end);
7892 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7893 std::size_t nbOfNodes(sz/2);
7894 std::copy(begin,end,(int *)tmp);
7895 for(std::size_t j=1;j<nbOfNodes;j++)
7897 begin[j]=tmp[nbOfNodes-j];
7898 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7902 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7904 std::size_t sz=std::distance(begin,end);
7906 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7907 double vec0[3],vec1[3];
7908 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7909 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];
7910 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;
7913 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7915 std::size_t sz=std::distance(begin,end);
7917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7919 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7920 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7921 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7925 * 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)
7926 * 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
7929 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7930 * \param [in] coords the coordinates with nb of components exactly equal to 3
7931 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7932 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7933 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7935 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7937 int nbFaces=std::count(begin+1,end,-1)+1;
7938 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7939 double *vPtr=v->getPointer();
7940 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7941 double *pPtr=p->getPointer();
7942 const int *stFaceConn=begin+1;
7943 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7945 const int *endFaceConn=std::find(stFaceConn,end,-1);
7946 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7947 stFaceConn=endFaceConn+1;
7949 pPtr=p->getPointer(); vPtr=v->getPointer();
7950 DataArrayInt *comm1=0,*commI1=0;
7951 v->findCommonTuples(eps,-1,comm1,commI1);
7952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7953 const int *comm1Ptr=comm1->getConstPointer();
7954 const int *commI1Ptr=commI1->getConstPointer();
7955 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7956 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7958 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7959 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7960 mm->finishInsertingCells();
7962 for(int i=0;i<nbOfGrps1;i++)
7964 int vecId=comm1Ptr[commI1Ptr[i]];
7965 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7966 DataArrayInt *comm2=0,*commI2=0;
7967 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7969 const int *comm2Ptr=comm2->getConstPointer();
7970 const int *commI2Ptr=commI2->getConstPointer();
7971 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7972 for(int j=0;j<nbOfGrps2;j++)
7974 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7976 res->insertAtTheEnd(begin,end);
7977 res->pushBackSilent(-1);
7981 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7983 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7984 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7985 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7986 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7989 const int *idsNodePtr=idsNode->getConstPointer();
7990 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];
7991 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7992 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7993 if(std::abs(norm)>eps)
7995 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7996 mm3->rotate(center,vec,angle);
7998 mm3->changeSpaceDimension(2);
7999 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8000 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8001 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8002 int nbOfCells=mm4->getNumberOfCells();
8003 for(int k=0;k<nbOfCells;k++)
8006 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8007 res->pushBackSilent(idsNodePtr[*work]);
8008 res->pushBackSilent(-1);
8013 res->popBackSilent();
8017 * 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
8018 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
8020 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8021 * \param [in] coords coordinates expected to have 3 components.
8022 * \param [in] begin start of the nodal connectivity of the face.
8023 * \param [in] end end of the nodal connectivity (excluded) of the face.
8024 * \param [out] v the normalized vector of size 3
8025 * \param [out] p the pos of plane
8027 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
8029 std::size_t nbPoints=std::distance(begin,end);
8031 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8032 double vec[3]={0.,0.,0.};
8034 bool refFound=false;
8035 for(;j<nbPoints-1 && !refFound;j++)
8037 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8038 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8039 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8040 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8044 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8047 for(std::size_t i=j;i<nbPoints-1;i++)
8050 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8051 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8052 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8053 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8056 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8057 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];
8058 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8061 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8062 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8066 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8070 * This method tries to obtain a well oriented polyhedron.
8071 * If the algorithm fails, an exception will be thrown.
8073 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
8075 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8076 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8077 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8079 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8080 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8081 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8083 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8086 std::size_t smthChanged=0;
8087 for(std::size_t i=0;i<nbOfFaces;i++)
8089 endFace=std::find(bgFace+1,end,-1);
8090 nbOfEdgesInFace=std::distance(bgFace,endFace);
8094 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8096 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8097 std::pair<int,int> p2(p1.second,p1.first);
8098 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8099 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8100 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8105 std::reverse(bgFace+1,endFace);
8106 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8108 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8109 std::pair<int,int> p2(p1.second,p1.first);
8110 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8111 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8112 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8113 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8114 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8115 if(it!=edgesOK.end())
8118 edgesFinished.push_back(p1);
8121 edgesOK.push_back(p1);
8128 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8130 if(!edgesOK.empty())
8131 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8132 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8133 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8135 for(std::size_t i=0;i<nbOfFaces;i++)
8137 endFace=std::find(bgFace+1,end,-1);
8138 std::reverse(bgFace+1,endFace);
8145 * This method makes the assumption spacedimension == meshdimension == 2.
8146 * This method works only for linear cells.
8148 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8150 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
8152 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8154 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8155 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8156 int nbOfNodesExpected=m->getNumberOfNodes();
8157 if(m->getNumberOfCells()!=nbOfNodesExpected)
8158 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8159 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8160 const int *n2oPtr=n2o->getConstPointer();
8161 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8162 m->getReverseNodalConnectivity(revNodal,revNodalI);
8163 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8164 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8165 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8167 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
8168 if(nbOfNodesExpected<1)
8171 int prevNode=nodalPtr[nodalIPtr[0]+1];
8172 *work++=n2oPtr[prevNode];
8173 for(int i=1;i<nbOfNodesExpected;i++)
8175 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8177 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8178 conn.erase(prevNode);
8181 int curNode=*(conn.begin());
8182 *work++=n2oPtr[curNode];
8183 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8184 shar.erase(prevCell);
8187 prevCell=*(shar.begin());
8191 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8194 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8203 * This method makes the assumption spacedimension == meshdimension == 3.
8204 * This method works only for linear cells.
8206 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8208 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8210 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8211 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8212 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8213 const int *conn=m->getNodalConnectivity()->getConstPointer();
8214 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8215 int nbOfCells=m->getNumberOfCells();
8216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8217 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8220 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8221 for(int i=1;i<nbOfCells;i++)
8224 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8230 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8231 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8233 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8237 for(int i=0;i<nbOfNodesInCell;i++)
8238 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8239 else if(spaceDim==2)
8241 for(int i=0;i<nbOfNodesInCell;i++)
8243 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8248 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8251 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8253 int nbOfCells=getNumberOfCells();
8255 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8256 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};
8257 ofs << " <" << getVTKDataSetType() << ">\n";
8258 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8259 ofs << " <PointData>\n" << pointData << std::endl;
8260 ofs << " </PointData>\n";
8261 ofs << " <CellData>\n" << cellData << std::endl;
8262 ofs << " </CellData>\n";
8263 ofs << " <Points>\n";
8264 if(getSpaceDimension()==3)
8265 _coords->writeVTK(ofs,8,"Points");
8268 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8269 coo->writeVTK(ofs,8,"Points");
8271 ofs << " </Points>\n";
8272 ofs << " <Cells>\n";
8273 const int *cPtr=_nodal_connec->getConstPointer();
8274 const int *cIPtr=_nodal_connec_index->getConstPointer();
8275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8279 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8280 int szFaceOffsets=0,szConn=0;
8281 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8284 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8287 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8288 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8292 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8293 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8294 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8295 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8296 w4=std::copy(c.begin(),c.end(),w4);
8299 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8300 types->writeVTK(ofs,8,"UInt8","types");
8301 offsets->writeVTK(ofs,8,"Int32","offsets");
8302 if(szFaceOffsets!=0)
8303 {//presence of Polyhedra
8304 connectivity->reAlloc(szConn);
8305 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8307 w1=faces->getPointer();
8308 for(int i=0;i<nbOfCells;i++)
8309 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8311 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8313 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8314 for(int j=0;j<nbFaces;j++)
8316 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8317 *w1++=(int)std::distance(w6,w5);
8318 w1=std::copy(w6,w5,w1);
8322 faces->writeVTK(ofs,8,"Int32","faces");
8324 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8325 ofs << " </Cells>\n";
8326 ofs << " </Piece>\n";
8327 ofs << " </" << getVTKDataSetType() << ">\n";
8330 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8332 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8334 { stream << " Not set !"; return ; }
8335 stream << " Mesh dimension : " << _mesh_dim << ".";
8339 { stream << " No coordinates set !"; return ; }
8340 if(!_coords->isAllocated())
8341 { stream << " Coordinates set but not allocated !"; return ; }
8342 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8343 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8344 if(!_nodal_connec_index)
8345 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8346 if(!_nodal_connec_index->isAllocated())
8347 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8348 int lgth=_nodal_connec_index->getNumberOfTuples();
8349 int cpt=_nodal_connec_index->getNumberOfComponents();
8350 if(cpt!=1 || lgth<1)
8352 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8355 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8357 return std::string("UnstructuredGrid");
8361 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8362 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8363 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8365 * \param [in] m1 - the first input mesh which is a partitioned object.
8366 * \param [in] m2 - the second input mesh which is a partition tool.
8367 * \param [in] eps - precision used to detect coincident mesh entities.
8368 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8369 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8370 * this array using decrRef() as it is no more needed.
8371 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8372 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8373 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8374 * any cell of \a m2. The caller is to delete this array using decrRef() as
8375 * it is no more needed.
8376 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8377 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8378 * is no more needed.
8379 * \throw If the coordinates array is not set in any of the meshes.
8380 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8381 * \throw If any of the meshes is not a 2D mesh in 2D space.
8383 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8385 m1->checkFullyDefined();
8386 m2->checkFullyDefined();
8387 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8388 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8389 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8390 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8391 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8392 std::vector<double> addCoo,addCoordsQuadratic;
8393 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8394 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8395 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8396 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8397 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8399 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8400 std::vector< std::vector<int> > intersectEdge2;
8401 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8402 subDiv2.clear(); dd5=0; dd6=0;
8403 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8404 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8405 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8406 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8408 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8409 addCooDa->alloc((int)(addCoo.size())/2,2);
8410 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8411 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8412 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8413 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8414 std::vector<const DataArrayDouble *> coordss(4);
8415 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8416 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8417 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8422 ret->setConnectivity(conn,connI,true);
8423 ret->setCoords(coo);
8424 cellNb1=c1.retn(); cellNb2=c2.retn();
8428 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8429 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8430 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8431 const std::vector<double>& addCoords,
8432 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8434 static const int SPACEDIM=2;
8435 std::vector<double> bbox1,bbox2;
8436 const double *coo1=m1->getCoords()->getConstPointer();
8437 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8438 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8439 int offset1=m1->getNumberOfNodes();
8440 const double *coo2=m2->getCoords()->getConstPointer();
8441 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8442 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8443 int offset2=offset1+m2->getNumberOfNodes();
8444 int offset3=offset2+((int)addCoords.size())/2;
8445 m1->getBoundingBoxForBBTree(bbox1);
8446 m2->getBoundingBoxForBBTree(bbox2);
8447 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8448 int ncell1=m1->getNumberOfCells();
8450 for(int i=0;i<ncell1;i++)
8452 std::vector<int> candidates2;
8453 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8454 std::map<INTERP_KERNEL::Node *,int> mapp;
8455 std::map<int,INTERP_KERNEL::Node *> mappRev;
8456 INTERP_KERNEL::QuadraticPolygon pol1;
8457 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8458 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8459 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8460 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8461 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8463 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
8464 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8465 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8466 for(it1.first();!it1.finished();it1.next())
8467 edges1.insert(it1.current()->getPtr());
8469 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8470 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8472 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8474 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8475 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8476 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8477 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8478 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8481 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8483 pol1.initLocationsWithOther(pol2s[ii]);
8484 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8485 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8486 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8492 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8494 catch(INTERP_KERNEL::Exception& e)
8496 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();
8497 throw INTERP_KERNEL::Exception(oss.str().c_str());
8500 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8501 (*it).second->decrRef();
8506 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8509 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8510 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8511 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8512 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8513 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8515 static const int SPACEDIM=2;
8516 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8517 desc2=DataArrayInt::New();
8518 descIndx2=DataArrayInt::New();
8519 revDesc2=DataArrayInt::New();
8520 revDescIndx2=DataArrayInt::New();
8521 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8522 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8523 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8524 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8525 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8526 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8527 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8528 std::vector<double> bbox1,bbox2;
8529 m1Desc->getBoundingBoxForBBTree(bbox1);
8530 m2Desc->getBoundingBoxForBBTree(bbox2);
8531 int ncell1=m1Desc->getNumberOfCells();
8532 int ncell2=m2Desc->getNumberOfCells();
8533 intersectEdge1.resize(ncell1);
8534 colinear2.resize(ncell2);
8535 subDiv2.resize(ncell2);
8536 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8537 std::vector<int> candidates1(1);
8538 int offset1=m1->getNumberOfNodes();
8539 int offset2=offset1+m2->getNumberOfNodes();
8540 for(int i=0;i<ncell1;i++)
8542 std::vector<int> candidates2;
8543 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8544 if(!candidates2.empty())
8546 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8547 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8549 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8550 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8555 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8557 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8558 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8562 * This method performs the 2nd step of Partition of 2D mesh.
8563 * This method has 4 inputs :
8564 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8565 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8566 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8567 * 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'
8568 * @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'
8569 * @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.
8570 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8572 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)
8574 int offset1=m1->getNumberOfNodes();
8575 int ncell=m2->getNumberOfCells();
8576 const int *c=m2->getNodalConnectivity()->getConstPointer();
8577 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8578 const double *coo=m2->getCoords()->getConstPointer();
8579 const double *cooBis=m1->getCoords()->getConstPointer();
8580 int offset2=offset1+m2->getNumberOfNodes();
8581 intersectEdge.resize(ncell);
8582 for(int i=0;i<ncell;i++,cI++)
8584 const std::vector<int>& divs=subDiv[i];
8585 int nnode=cI[1]-cI[0]-1;
8586 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8587 std::map<INTERP_KERNEL::Node *, int> mapp22;
8588 for(int j=0;j<nnode;j++)
8590 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8591 int nnid=c[(*cI)+j+1];
8592 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8593 mapp22[nn]=nnid+offset1;
8595 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8596 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8597 ((*it).second.first)->decrRef();
8598 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8599 std::map<INTERP_KERNEL::Node *,int> mapp3;
8600 for(std::size_t j=0;j<divs.size();j++)
8603 INTERP_KERNEL::Node *tmp=0;
8605 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8607 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8609 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8613 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8614 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8621 * 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).
8622 * 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
8623 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8624 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8625 * @param nodesOnPlane, returns all the nodes that are on the plane.
8626 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
8627 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8628 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
8629 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8630 * @param desc is the descending connectivity 3DSurf->3DCurve
8631 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
8632 * @param cut3DSuf input/output param.
8634 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8635 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8636 const int *desc, const int *descIndx,
8637 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8639 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8640 int nbOf3DSurfCell=(int)cut3DSurf.size();
8641 for(int i=0;i<nbOf3DSurfCell;i++)
8643 std::vector<int> res;
8644 int offset=descIndx[i];
8645 int nbOfSeg=descIndx[i+1]-offset;
8646 for(int j=0;j<nbOfSeg;j++)
8648 int edgeId=desc[offset+j];
8649 int status=cut3DCurve[edgeId];
8653 res.push_back(status);
8656 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8657 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8665 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8671 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8672 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8675 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8679 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8684 {// case when plane is on a multi colinear edge of a polyhedron
8685 if((int)res.size()==2*nbOfSeg)
8687 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8690 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8697 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8698 * 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).
8699 * 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
8700 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8701 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8702 * @param desc is the descending connectivity 3D->3DSurf
8703 * @param descIndx is the descending connectivity index 3D->3DSurf
8705 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8706 const int *desc, const int *descIndx,
8707 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8709 checkFullyDefined();
8710 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8711 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8712 const int *nodal3D=_nodal_connec->getConstPointer();
8713 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8714 int nbOfCells=getNumberOfCells();
8715 for(int i=0;i<nbOfCells;i++)
8717 std::map<int, std::set<int> > m;
8718 int offset=descIndx[i];
8719 int nbOfFaces=descIndx[i+1]-offset;
8722 for(int j=0;j<nbOfFaces;j++)
8724 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8725 if(p.first!=-1 && p.second!=-1)
8729 start=p.first; end=p.second;
8730 m[p.first].insert(p.second);
8731 m[p.second].insert(p.first);
8735 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8736 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8737 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8738 INTERP_KERNEL::NormalizedCellType cmsId;
8739 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8740 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8741 for(unsigned k=0;k<nbOfNodesSon;k++)
8743 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8744 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8751 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8755 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8756 const std::set<int>& s=(*it).second;
8757 std::set<int> s2; s2.insert(prev);
8759 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8762 int val=*s3.begin();
8763 conn.push_back(start);
8770 conn.push_back(end);
8773 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8774 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8775 cellIds->pushBackSilent(i);
8781 * 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
8782 * 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
8783 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8784 * 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
8785 * 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.
8787 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8789 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8791 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8794 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8795 if(cm.getDimension()==2)
8797 const int *node=nodalConnBg+1;
8798 int startNode=*node++;
8799 double refX=coords[2*startNode];
8800 for(;node!=nodalConnEnd;node++)
8802 if(coords[2*(*node)]<refX)
8805 refX=coords[2*startNode];
8808 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8812 double angle0=-M_PI/2;
8817 double angleNext=0.;
8818 while(nextNode!=startNode)
8822 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8824 if(*node!=tmpOut.back() && *node!=prevNode)
8826 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8827 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8832 res=angle0-angleM+2.*M_PI;
8841 if(nextNode!=startNode)
8843 angle0=angleNext-M_PI;
8846 prevNode=tmpOut.back();
8847 tmpOut.push_back(nextNode);
8850 std::vector<int> tmp3(2*(sz-1));
8851 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8852 std::copy(nodalConnBg+1,nodalConnEnd,it);
8853 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8855 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8858 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8860 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8865 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8866 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8878 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8879 * 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.
8881 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8882 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8883 * \param [in,out] arr array in which the remove operation will be done.
8884 * \param [in,out] arrIndx array in the remove operation will modify
8885 * \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])
8886 * \return true if \b arr and \b arrIndx have been modified, false if not.
8888 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8890 if(!arrIndx || !arr)
8891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8892 if(offsetForRemoval<0)
8893 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8894 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8895 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8896 int *arrIPtr=arrIndx->getPointer();
8899 const int *arrPtr=arr->getConstPointer();
8900 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8901 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8903 if(*arrIPtr-previousArrI>offsetForRemoval)
8905 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8907 if(s.find(*work)==s.end())
8908 arrOut.push_back(*work);
8911 previousArrI=*arrIPtr;
8912 *arrIPtr=(int)arrOut.size();
8914 if(arr->getNumberOfTuples()==(int)arrOut.size())
8916 arr->alloc((int)arrOut.size(),1);
8917 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8922 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8923 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8924 * The selection of extraction is done standardly in new2old format.
8925 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8927 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8928 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8929 * \param [in] arrIn arr origin array from which the extraction will be done.
8930 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8931 * \param [out] arrOut the resulting array
8932 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8934 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8935 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8937 if(!arrIn || !arrIndxIn)
8938 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8939 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8940 const int *arrInPtr=arrIn->getConstPointer();
8941 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8942 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8943 int maxSizeOfArr=arrIn->getNumberOfTuples();
8944 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8945 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8946 arrIo->alloc((int)(sz+1),1);
8947 const int *idsIt=idsOfSelectBg;
8948 int *work=arrIo->getPointer();
8951 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8953 if(*idsIt>=0 && *idsIt<nbOfGrps)
8954 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8957 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8958 throw INTERP_KERNEL::Exception(oss.str().c_str());
8964 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8965 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8966 throw INTERP_KERNEL::Exception(oss.str().c_str());
8969 arro->alloc(lgth,1);
8970 work=arro->getPointer();
8971 idsIt=idsOfSelectBg;
8972 for(std::size_t i=0;i<sz;i++,idsIt++)
8974 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8975 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8978 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8979 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8980 throw INTERP_KERNEL::Exception(oss.str().c_str());
8984 arrIndexOut=arrIo.retn();
8988 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8989 * 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
8990 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8991 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8993 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8994 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8995 * \param [in] arrIn arr origin array from which the extraction will be done.
8996 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8997 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8998 * \param [in] srcArrIndex index array of \b srcArr
8999 * \param [out] arrOut the resulting array
9000 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9002 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9004 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9005 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9006 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9008 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9009 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9012 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9013 std::vector<bool> v(nbOfTuples,true);
9015 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9016 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9017 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9019 if(*it>=0 && *it<nbOfTuples)
9022 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9026 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9027 throw INTERP_KERNEL::Exception(oss.str().c_str());
9030 srcArrIndexPtr=srcArrIndex->getConstPointer();
9031 arrIo->alloc(nbOfTuples+1,1);
9032 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9033 const int *arrInPtr=arrIn->getConstPointer();
9034 const int *srcArrPtr=srcArr->getConstPointer();
9035 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9036 int *arroPtr=arro->getPointer();
9037 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9041 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9042 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9046 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9047 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9048 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9052 arrIndexOut=arrIo.retn();
9056 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9057 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9059 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9060 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9061 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9062 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9063 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9064 * \param [in] srcArrIndex index array of \b srcArr
9066 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9068 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9069 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9071 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9072 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9073 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9074 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9075 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9076 int *arrInOutPtr=arrInOut->getPointer();
9077 const int *srcArrPtr=srcArr->getConstPointer();
9078 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9080 if(*it>=0 && *it<nbOfTuples)
9082 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9083 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9086 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] !";
9087 throw INTERP_KERNEL::Exception(oss.str().c_str());
9092 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9093 throw INTERP_KERNEL::Exception(oss.str().c_str());
9099 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9100 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9101 * 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]].
9102 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9103 * A negative value in \b arrIn means that it is ignored.
9104 * 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.
9106 * \param [in] arrIn arr origin array from which the extraction will be done.
9107 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9108 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9109 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9111 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9113 int seed=0,nbOfDepthPeelingPerformed=0;
9114 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9118 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9119 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9120 * 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]].
9121 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9122 * A negative value in \b arrIn means that it is ignored.
9123 * 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.
9124 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9125 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9126 * \param [in] arrIn arr origin array from which the extraction will be done.
9127 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9128 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9129 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9130 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9131 * \sa MEDCouplingUMesh::partitionBySpreadZone
9133 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9135 nbOfDepthPeelingPerformed=0;
9137 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9138 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9141 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9145 std::vector<bool> fetched(nbOfTuples,false);
9146 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9149 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)
9151 nbOfDepthPeelingPerformed=0;
9152 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9154 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9155 std::vector<bool> fetched2(nbOfTuples,false);
9157 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9159 if(*seedElt>=0 && *seedElt<nbOfTuples)
9160 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9162 { 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()); }
9164 const int *arrInPtr=arrIn->getConstPointer();
9165 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9166 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9167 std::vector<int> idsToFetch1(seedBg,seedEnd);
9168 std::vector<int> idsToFetch2;
9169 std::vector<int> *idsToFetch=&idsToFetch1;
9170 std::vector<int> *idsToFetchOther=&idsToFetch2;
9171 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9173 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9174 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9176 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9177 std::swap(idsToFetch,idsToFetchOther);
9178 idsToFetchOther->clear();
9179 nbOfDepthPeelingPerformed++;
9181 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9184 int *retPtr=ret->getPointer();
9185 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9192 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9193 * 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
9194 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9195 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9197 * \param [in] start begin of set of ids of the input extraction (included)
9198 * \param [in] end end of set of ids of the input extraction (excluded)
9199 * \param [in] step step of the set of ids in range mode.
9200 * \param [in] arrIn arr origin array from which the extraction will be done.
9201 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9202 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9203 * \param [in] srcArrIndex index array of \b srcArr
9204 * \param [out] arrOut the resulting array
9205 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9207 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9209 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9210 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9211 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9213 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9214 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9217 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9219 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9220 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9221 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9223 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9225 if(it>=0 && it<nbOfTuples)
9226 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9229 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9230 throw INTERP_KERNEL::Exception(oss.str().c_str());
9233 srcArrIndexPtr=srcArrIndex->getConstPointer();
9234 arrIo->alloc(nbOfTuples+1,1);
9235 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9236 const int *arrInPtr=arrIn->getConstPointer();
9237 const int *srcArrPtr=srcArr->getConstPointer();
9238 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9239 int *arroPtr=arro->getPointer();
9240 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9242 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9245 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9246 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9250 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9251 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9255 arrIndexOut=arrIo.retn();
9259 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9260 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9262 * \param [in] start begin of set of ids of the input extraction (included)
9263 * \param [in] end end of set of ids of the input extraction (excluded)
9264 * \param [in] step step of the set of ids in range mode.
9265 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9266 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9267 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9268 * \param [in] srcArrIndex index array of \b srcArr
9270 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9272 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9273 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9275 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9277 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9278 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9279 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9280 int *arrInOutPtr=arrInOut->getPointer();
9281 const int *srcArrPtr=srcArr->getConstPointer();
9282 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9284 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9286 if(it>=0 && it<nbOfTuples)
9288 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9289 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9292 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9293 throw INTERP_KERNEL::Exception(oss.str().c_str());
9298 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9299 throw INTERP_KERNEL::Exception(oss.str().c_str());
9305 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9306 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9307 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9308 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9309 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9311 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9313 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9315 checkFullyDefined();
9316 int mdim=getMeshDimension();
9317 int spaceDim=getSpaceDimension();
9319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9320 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9321 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9322 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9324 ret->setCoords(getCoords());
9325 ret->allocateCells((int)partition.size());
9327 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9329 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9334 cell=tmp->buildUnionOf2DMesh();
9337 cell=tmp->buildUnionOf3DMesh();
9340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9343 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9346 ret->finishInsertingCells();
9351 * This method partitions \b this into contiguous zone.
9352 * This method only needs a well defined connectivity. Coordinates are not considered here.
9353 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9355 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9358 int nbOfCellsCur=getNumberOfCells();
9359 std::vector<DataArrayInt *> ret;
9362 DataArrayInt *neigh=0,*neighI=0;
9363 computeNeighborsOfCells(neigh,neighI);
9364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9365 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9366 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9368 while(seed<nbOfCellsCur)
9370 int nbOfPeelPerformed=0;
9371 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9372 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9374 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9375 ret.push_back((*it).retn());
9379 int nbOfCellsCur=getNumberOfCells();
9380 DataArrayInt *neigh=0,*neighI=0;
9381 computeNeighborsOfCells(neigh,neighI);
9382 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9384 std::vector<DataArrayInt *> ret;
9385 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9386 while(nbOfCellsCur>0)
9388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9391 ret2.push_back(tmp2); ret.push_back(tmp2);
9392 nbOfCellsCur=tmp3->getNumberOfTuples();
9395 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9396 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9400 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9403 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9410 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9411 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9413 * \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.
9414 * \return a newly allocated DataArrayInt to be managed by the caller.
9415 * \throw In case of \a code has not the right format (typically of size 3*n)
9417 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9420 std::size_t nb=code.size()/3;
9421 if(code.size()%3!=0)
9422 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9423 ret->alloc((int)nb,2);
9424 int *retPtr=ret->getPointer();
9425 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9427 retPtr[0]=code[3*i+2];
9428 retPtr[1]=code[3*i+2]+code[3*i+1];
9433 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9434 _own_cell(true),_cell_id(-1),_nb_cell(0)
9439 _nb_cell=mesh->getNumberOfCells();
9443 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9451 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9452 _own_cell(false),_cell_id(bg-1),
9459 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9462 if(_cell_id<_nb_cell)
9471 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9477 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9479 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9482 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9488 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9496 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9502 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9507 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9512 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9514 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9517 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9522 _nb_cell=mesh->getNumberOfCells();
9526 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9533 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9535 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9536 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9537 if(_cell_id<_nb_cell)
9539 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9540 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9541 int startId=_cell_id;
9542 _cell_id+=nbOfElems;
9543 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9549 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9553 _conn=mesh->getNodalConnectivity()->getPointer();
9554 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9558 void MEDCouplingUMeshCell::next()
9560 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9565 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9568 std::string MEDCouplingUMeshCell::repr() const
9570 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9572 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9574 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9578 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9581 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9583 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9584 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9586 return INTERP_KERNEL::NORM_ERROR;
9589 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9592 if(_conn_lgth!=NOTICABLE_FIRST_VAL)