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 \a 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.
376 * \warning this method does not throw any exception even if \a this is not defined.
378 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
384 * This method is a method that compares \a this and \a other.
385 * This method compares \b all attributes, even names and component names.
387 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
391 std::ostringstream oss; oss.precision(15);
392 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
395 reason="mesh given in input is not castable in MEDCouplingUMesh !";
398 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
400 if(_mesh_dim!=otherC->_mesh_dim)
402 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
406 if(_types!=otherC->_types)
408 oss << "umesh geometric type mismatch :\nThis geometric types are :";
409 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
410 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
411 oss << "\nOther geometric types are :";
412 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
413 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
417 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
418 if(_nodal_connec==0 || otherC->_nodal_connec==0)
420 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
423 if(_nodal_connec!=otherC->_nodal_connec)
424 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
426 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
429 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
430 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
432 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
435 if(_nodal_connec_index!=otherC->_nodal_connec_index)
436 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
438 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
445 * Checks if data arrays of this mesh (node coordinates, nodal
446 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
448 * \param [in] other - the mesh to compare with.
449 * \param [in] prec - precision value used to compare node coordinates.
450 * \return bool - \a true if the two meshes are same.
452 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
454 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
457 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
459 if(_mesh_dim!=otherC->_mesh_dim)
461 if(_types!=otherC->_types)
463 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
464 if(_nodal_connec==0 || otherC->_nodal_connec==0)
466 if(_nodal_connec!=otherC->_nodal_connec)
467 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
469 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
470 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
472 if(_nodal_connec_index!=otherC->_nodal_connec_index)
473 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
479 * Checks if \a this and \a other meshes are geometrically equivalent, else an
480 * exception is thrown. The meshes are
481 * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
482 * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
483 * the \a other mesh (with use of a specified cell comparison technique). The mapping
484 * from \a other to \a this for nodes and cells is returned via out parameters.
485 * \param [in] other - the mesh to compare with.
486 * \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
487 * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
488 * \param [in] prec - the precision used to compare nodes of the two meshes.
489 * \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
490 * to delete this array using decrRef() as it is no more needed.
491 * \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
492 * to delete this array using decrRef() as it is no more needed.
493 * \throw If the two meshes do not match.
495 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
496 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
498 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
499 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
501 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
503 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
504 MEDCouplingMesh::checkFastEquivalWith(other,prec);
505 if(_types!=otherC->_types)
506 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
507 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
510 int oldNbOfNodes=getNumberOfNodes();
511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
514 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
515 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
516 if(pt!=da->getConstPointer()+da->getNbOfElems())
517 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
518 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
520 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
521 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
524 da=m->zipConnectivityTraducer(cellCompPol);
525 int nbCells=getNumberOfCells();
528 maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
529 pt=std::find_if(da->getConstPointer()+nbCells,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
530 if(pt!=da->getConstPointer()+da->getNbOfElems())
531 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(nbCells,da->getNbOfElems(),1);
533 nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
534 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
538 * Checks if \a this and \a other meshes are geometrically equivalent, else an
539 * exception is thrown. The meshes are considered equivalent if (1) they share one
540 * node coordinates array and (2) they contain the same cells (with use of a specified
541 * cell comparison technique). The mapping from cells of the \a other to ones of \a this
542 * is returned via an out parameter.
543 * \param [in] other - the mesh to compare with.
544 * \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
545 * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
546 * \param [in] prec - a not used parameter.
547 * \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
548 * to delete this array using decrRef() as it is no more needed.
549 * \throw If the two meshes do not match.
551 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
552 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
554 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
555 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
557 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
559 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
560 MEDCouplingMesh::checkFastEquivalWith(other,prec);
561 if(_types!=otherC->_types)
562 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
563 if(_coords!=otherC->_coords)
564 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
565 std::vector<const MEDCouplingUMesh *> ms(2);
568 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
570 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
571 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
572 if(pt!=da->getConstPointer()+da->getNbOfElems())
574 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
577 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
581 * Checks if \a this and \a other meshes are geometrically equivalent with high
582 * probability, else an exception is thrown. The meshes are considered equivalent if
583 * (1) meshes contain the same number of nodes and the same number of elements of the
584 * same types (2) three cells of the two meshes (first, last and middle) are based
585 * on coincident nodes (with a specified precision).
586 * \param [in] other - the mesh to compare with.
587 * \param [in] prec - the precision used to compare nodes of the two meshes.
588 * \throw If the two meshes do not match.
590 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
592 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
594 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
595 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
596 int nbOfCells=getNumberOfCells();
600 status&=areCellsFrom2MeshEqual(otherC,0,prec);
601 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
602 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
604 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
608 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
609 * cells each node belongs to.
610 * \warning For speed reasons, this method does not check if node ids in the nodal
611 * connectivity correspond to the size of node coordinates array.
612 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
613 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
614 * dividing cell ids in \a revNodal into groups each referring to one
615 * node. Its every element (except the last one) is an index pointing to the
616 * first id of a group of cells. For example cells sharing the node #1 are
617 * described by following range of indices:
618 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
619 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
620 * Number of cells sharing the *i*-th node is
621 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
622 * \throw If the coordinates array is not set.
623 * \throw If the nodal connectivity of cells is not defined.
625 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
626 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
628 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
631 int nbOfNodes=getNumberOfNodes();
632 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
633 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
634 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
635 const int *conn=_nodal_connec->getConstPointer();
636 const int *connIndex=_nodal_connec_index->getConstPointer();
637 int nbOfCells=getNumberOfCells();
638 int nbOfEltsInRevNodal=0;
639 for(int eltId=0;eltId<nbOfCells;eltId++)
641 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
642 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
643 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
644 if(*iter>=0)//for polyhedrons
646 nbOfEltsInRevNodal++;
647 revNodalIndxPtr[(*iter)+1]++;
650 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
651 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
652 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
653 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
654 for(int eltId=0;eltId<nbOfCells;eltId++)
656 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
657 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
658 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
659 if(*iter>=0)//for polyhedrons
660 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
666 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
671 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
677 if(cm.getOrientationStatus(nb,conn1,conn2))
684 class MinusOneSonsGenerator
687 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
688 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
689 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
690 static const int DELTA=1;
692 const INTERP_KERNEL::CellModel& _cm;
695 class MinusOneSonsGeneratorBiQuadratic
698 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
699 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
700 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
701 static const int DELTA=1;
703 const INTERP_KERNEL::CellModel& _cm;
706 class MinusTwoSonsGenerator
709 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
710 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
711 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
712 static const int DELTA=2;
714 const INTERP_KERNEL::CellModel& _cm;
720 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
721 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
722 * describing correspondence between cells of \a this and the result meshes are
723 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
724 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
725 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
726 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
727 * \warning For speed reasons, this method does not check if node ids in the nodal
728 * connectivity correspond to the size of node coordinates array.
729 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
730 * to write this mesh to the MED file, its cells must be sorted using
731 * sortCellsInMEDFileFrmt().
732 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
733 * each cell of \a this mesh.
734 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
735 * dividing cell ids in \a desc into groups each referring to one
736 * cell of \a this mesh. Its every element (except the last one) is an index
737 * pointing to the first id of a group of cells. For example cells of the
738 * result mesh bounding the cell #1 of \a this mesh are described by following
740 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
741 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
742 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
743 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
744 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
745 * by each cell of the result mesh.
746 * \param [in,out] revDescIndx - the array, of length one more than number of cells
747 * in the result mesh,
748 * dividing cell ids in \a revDesc into groups each referring to one
749 * cell of the result mesh the same way as \a descIndx divides \a desc.
750 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
751 * delete this mesh using decrRef() as it is no more needed.
752 * \throw If the coordinates array is not set.
753 * \throw If the nodal connectivity of cells is node defined.
754 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
755 * revDescIndx == NULL.
757 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
758 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
759 * \sa buildDescendingConnectivity2()
761 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
763 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
767 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
768 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
769 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
770 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
771 * \sa MEDCouplingUMesh::buildDescendingConnectivity
773 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
776 if(getMeshDimension()!=3)
777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
778 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
782 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
783 * this->getMeshDimension(), that bound cells of \a this mesh. In
784 * addition arrays describing correspondence between cells of \a this and the result
785 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
786 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
787 * mesh. This method differs from buildDescendingConnectivity() in that apart
788 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
789 * result meshes. So a positive id means that order of nodes in corresponding cells
790 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
791 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
792 * i.e. cell ids are one-based.
793 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
794 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
795 * \warning For speed reasons, this method does not check if node ids in the nodal
796 * connectivity correspond to the size of node coordinates array.
797 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
798 * to write this mesh to the MED file, its cells must be sorted using
799 * sortCellsInMEDFileFrmt().
800 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
801 * each cell of \a this mesh.
802 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
803 * dividing cell ids in \a desc into groups each referring to one
804 * cell of \a this mesh. Its every element (except the last one) is an index
805 * pointing to the first id of a group of cells. For example cells of the
806 * result mesh bounding the cell #1 of \a this mesh are described by following
808 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
809 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
810 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
811 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
812 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
813 * by each cell of the result mesh.
814 * \param [in,out] revDescIndx - the array, of length one more than number of cells
815 * in the result mesh,
816 * dividing cell ids in \a revDesc into groups each referring to one
817 * cell of the result mesh the same way as \a descIndx divides \a desc.
818 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
819 * shares the node coordinates array with \a this mesh. The caller is to
820 * delete this mesh using decrRef() as it is no more needed.
821 * \throw If the coordinates array is not set.
822 * \throw If the nodal connectivity of cells is node defined.
823 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
824 * revDescIndx == NULL.
826 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
827 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
828 * \sa buildDescendingConnectivity()
830 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
832 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
836 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
837 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
838 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
839 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
841 * \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
842 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843 * \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.
845 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
851 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
853 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
857 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
858 * 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,
859 * excluding a set of meshdim-1 cells in input descending connectivity.
860 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
861 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
862 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
864 * \param [in] desc descending connectivity array.
865 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
866 * \param [in] revDesc reverse descending connectivity array.
867 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
868 * \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
869 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
870 * \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.
872 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
873 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
875 if(!desc || !descIndx || !revDesc || !revDescIndx)
876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
877 const int *descPtr=desc->getConstPointer();
878 const int *descIPtr=descIndx->getConstPointer();
879 const int *revDescPtr=revDesc->getConstPointer();
880 const int *revDescIPtr=revDescIndx->getConstPointer();
882 int nbCells=descIndx->getNumberOfTuples()-1;
883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
885 int *out1Ptr=out1->getPointer();
887 out0->reserve(desc->getNumberOfTuples());
888 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
890 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
892 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
894 out0->insertAtTheEnd(s.begin(),s.end());
896 *out1Ptr=out0->getNumberOfTuples();
898 neighbors=out0.retn();
899 neighborsIndx=out1.retn();
905 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
906 * For speed reasons no check of this will be done.
908 template<class SonsGenerator>
909 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
911 if(!desc || !descIndx || !revDesc || !revDescIndx)
912 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
913 checkConnectivityFullyDefined();
914 int nbOfCells=getNumberOfCells();
915 int nbOfNodes=getNumberOfNodes();
916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
917 int *revNodalIndxPtr=revNodalIndx->getPointer();
918 const int *conn=_nodal_connec->getConstPointer();
919 const int *connIndex=_nodal_connec_index->getConstPointer();
920 std::string name="Mesh constituent of "; name+=getName();
921 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
922 ret->setCoords(getCoords());
923 ret->allocateCells(2*nbOfCells);
924 descIndx->alloc(nbOfCells+1,1);
925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
926 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
927 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
929 int pos=connIndex[eltId];
930 int posP1=connIndex[eltId+1];
931 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
932 SonsGenerator sg(cm);
933 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
934 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
935 for(unsigned i=0;i<nbOfSons;i++)
937 INTERP_KERNEL::NormalizedCellType cmsId;
938 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
939 for(unsigned k=0;k<nbOfNodesSon;k++)
941 revNodalIndxPtr[tmp[k]+1]++;
942 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
943 revDesc2->pushBackSilent(eltId);
945 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
947 int nbOfCellsM1=ret->getNumberOfCells();
948 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
949 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
950 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
951 int *revNodalPtr=revNodal->getPointer();
952 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
953 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
954 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
956 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
957 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
958 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
959 if(*iter>=0)//for polyhedrons
960 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
963 DataArrayInt *commonCells=0,*commonCellsI=0;
964 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
966 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
967 int newNbOfCellsM1=-1;
968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
969 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
970 std::vector<bool> isImpacted(nbOfCellsM1,false);
971 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
972 for(int work2=work[0];work2!=work[1];work2++)
973 isImpacted[commonCellsPtr[work2]]=true;
974 const int *o2nM1Ptr=o2nM1->getConstPointer();
975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
976 const int *n2oM1Ptr=n2oM1->getConstPointer();
977 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
978 ret2->copyTinyInfoFrom(this);
979 desc->alloc(descIndx->back(),1);
980 int *descPtr=desc->getPointer();
981 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
982 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
985 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
988 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
990 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
991 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
994 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
997 revDesc->reserve(newNbOfCellsM1);
998 revDescIndx->alloc(newNbOfCellsM1+1,1);
999 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1000 const int *revDesc2Ptr=revDesc2->getConstPointer();
1001 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1003 int oldCellIdM1=n2oM1Ptr[i];
1004 if(!isImpacted[oldCellIdM1])
1006 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1007 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1011 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1012 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1013 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1021 struct MEDCouplingAccVisit
1023 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1024 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1025 int _new_nb_of_nodes;
1031 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1032 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1033 * array of cell ids. Pay attention that after conversion all algorithms work slower
1034 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1035 * conversion due presence of invalid ids in the array of cells to convert, as a
1036 * result \a this mesh contains some already converted elements. In this case the 2D
1037 * mesh remains valid but 3D mesh becomes \b inconsistent!
1038 * \warning This method can significantly modify the order of geometric types in \a this,
1039 * hence, to write this mesh to the MED file, its cells must be sorted using
1040 * sortCellsInMEDFileFrmt().
1041 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1042 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1043 * cellIdsToConvertBg.
1044 * \throw If the coordinates array is not set.
1045 * \throw If the nodal connectivity of cells is node defined.
1046 * \throw If dimension of \a this mesh is not either 2 or 3.
1048 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1049 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1051 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1053 checkFullyDefined();
1054 int dim=getMeshDimension();
1056 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1057 int nbOfCells=getNumberOfCells();
1060 const int *connIndex=_nodal_connec_index->getConstPointer();
1061 int *conn=_nodal_connec->getPointer();
1062 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1064 if(*iter>=0 && *iter<nbOfCells)
1066 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1067 if(!cm.isQuadratic())
1068 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1070 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1074 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1075 oss << " in range [0," << nbOfCells << ") !";
1076 throw INTERP_KERNEL::Exception(oss.str().c_str());
1082 int *connIndex=_nodal_connec_index->getPointer();
1083 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1084 const int *connOld=_nodal_connec->getConstPointer();
1085 int connOldLgth=_nodal_connec->getNbOfElems();
1086 std::vector<int> connNew(connOld,connOld+connOldLgth);
1087 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1089 if(*iter>=0 && *iter<nbOfCells)
1091 int pos=connIndex[*iter];
1092 int posP1=connIndex[(*iter)+1];
1093 int lgthOld=posP1-pos-1;
1094 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1095 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1096 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1097 int *tmp=new int[nbOfFaces*lgthOld];
1099 for(int j=0;j<(int)nbOfFaces;j++)
1101 INTERP_KERNEL::NormalizedCellType type;
1102 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1106 std::size_t newLgth=std::distance(tmp,work)-1;
1107 std::size_t delta=newLgth-lgthOld;
1108 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1109 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1110 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1115 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1116 oss << " in range [0," << nbOfCells << ") !";
1117 throw INTERP_KERNEL::Exception(oss.str().c_str());
1120 _nodal_connec->alloc((int)connNew.size(),1);
1121 int *newConnPtr=_nodal_connec->getPointer();
1122 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1128 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1129 * polyhedrons (if \a this is a 3D mesh).
1130 * \warning As this method is purely for user-friendliness and no optimization is
1131 * done to avoid construction of a useless vector, this method can be costly
1133 * \throw If the coordinates array is not set.
1134 * \throw If the nodal connectivity of cells is node defined.
1135 * \throw If dimension of \a this mesh is not either 2 or 3.
1137 void MEDCouplingUMesh::convertAllToPoly()
1139 int nbOfCells=getNumberOfCells();
1140 std::vector<int> cellIds(nbOfCells);
1141 for(int i=0;i<nbOfCells;i++)
1143 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1147 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1148 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1149 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1150 * base facet of the volume and the second half of nodes describes an opposite facet
1151 * having the same number of nodes as the base one. This method converts such
1152 * connectivity to a valid polyhedral format where connectivity of each facet is
1153 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1154 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1155 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1156 * a correct orientation of the first facet of a polyhedron, else orientation of a
1157 * corrected cell is reverse.<br>
1158 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1159 * it releases the user from boring description of polyhedra connectivity in the valid
1161 * \throw If \a this->getMeshDimension() != 3.
1162 * \throw If \a this->getSpaceDimension() != 3.
1163 * \throw If the nodal connectivity of cells is not defined.
1164 * \throw If the coordinates array is not set.
1165 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1166 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1168 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1169 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1171 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1173 checkFullyDefined();
1174 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1175 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1176 int nbOfCells=getNumberOfCells();
1177 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1178 newCi->alloc(nbOfCells+1,1);
1179 int *newci=newCi->getPointer();
1180 const int *ci=_nodal_connec_index->getConstPointer();
1181 const int *c=_nodal_connec->getConstPointer();
1183 for(int i=0;i<nbOfCells;i++)
1185 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1186 if(type==INTERP_KERNEL::NORM_POLYHED)
1188 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1190 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1191 throw INTERP_KERNEL::Exception(oss.str().c_str());
1193 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1196 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 !";
1197 throw INTERP_KERNEL::Exception(oss.str().c_str());
1200 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)
1203 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1206 newC->alloc(newci[nbOfCells],1);
1207 int *newc=newC->getPointer();
1208 for(int i=0;i<nbOfCells;i++)
1210 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1211 if(type==INTERP_KERNEL::NORM_POLYHED)
1213 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1214 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1216 for(std::size_t j=0;j<n1;j++)
1218 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1220 newc[n1+5*j+1]=c[ci[i]+1+j];
1221 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1222 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1223 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1228 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1230 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1231 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1236 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1237 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1238 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1239 * to write this mesh to the MED file, its cells must be sorted using
1240 * sortCellsInMEDFileFrmt().
1241 * \return \c true if at least one cell has been converted, \c false else. In the
1242 * last case the nodal connectivity remains unchanged.
1243 * \throw If the coordinates array is not set.
1244 * \throw If the nodal connectivity of cells is not defined.
1245 * \throw If \a this->getMeshDimension() < 0.
1247 bool MEDCouplingUMesh::unPolyze()
1249 checkFullyDefined();
1250 int mdim=getMeshDimension();
1252 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1255 int nbOfCells=getNumberOfCells();
1258 int initMeshLgth=getMeshLength();
1259 int *conn=_nodal_connec->getPointer();
1260 int *index=_nodal_connec_index->getPointer();
1265 for(int i=0;i<nbOfCells;i++)
1267 lgthOfCurCell=index[i+1]-posOfCurCell;
1268 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1269 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1270 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1274 switch(cm.getDimension())
1278 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1279 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1280 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1285 int nbOfFaces,lgthOfPolyhConn;
1286 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1287 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1292 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1296 ret=ret || (newType!=type);
1297 conn[newPos]=newType;
1299 posOfCurCell=index[i+1];
1304 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1305 newPos+=lgthOfCurCell;
1306 posOfCurCell+=lgthOfCurCell;
1310 if(newPos!=initMeshLgth)
1311 _nodal_connec->reAlloc(newPos);
1318 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1319 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1320 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1322 * \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
1325 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1327 checkFullyDefined();
1328 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1330 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1331 coords->recenterForMaxPrecision(eps);
1333 int nbOfCells=getNumberOfCells();
1334 const int *conn=_nodal_connec->getConstPointer();
1335 const int *index=_nodal_connec_index->getConstPointer();
1336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1337 connINew->alloc(nbOfCells+1,1);
1338 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1341 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1343 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1345 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1349 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1350 *connINewPtr=connNew->getNumberOfTuples();
1353 setConnectivity(connNew,connINew,false);
1357 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1358 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1359 * the format of returned DataArrayInt instance.
1361 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1362 * \sa MEDCouplingUMesh::getNodeIdsInUse
1364 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1366 checkConnectivityFullyDefined();
1367 int nbOfCells=getNumberOfCells();
1368 const int *connIndex=_nodal_connec_index->getConstPointer();
1369 const int *conn=_nodal_connec->getConstPointer();
1370 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1371 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1372 std::vector<bool> retS(maxElt,false);
1373 for(int i=0;i<nbOfCells;i++)
1374 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1378 for(int i=0;i<maxElt;i++)
1381 DataArrayInt *ret=DataArrayInt::New();
1383 int *retPtr=ret->getPointer();
1384 for(int i=0;i<maxElt;i++)
1391 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1392 * \sa MEDCouplingUMesh::getNodeIdsInUse
1394 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1396 int nbOfNodes=(int)nodeIdsInUse.size();
1397 int nbOfCells=getNumberOfCells();
1398 const int *connIndex=_nodal_connec_index->getConstPointer();
1399 const int *conn=_nodal_connec->getConstPointer();
1400 for(int i=0;i<nbOfCells;i++)
1401 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1404 if(conn[j]<nbOfNodes)
1405 nodeIdsInUse[conn[j]]=true;
1408 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1409 throw INTERP_KERNEL::Exception(oss.str().c_str());
1415 * Finds nodes not used in any cell and returns an array giving a new id to every node
1416 * by excluding the unused nodes, for which the array holds -1. The result array is
1417 * a mapping in "Old to New" mode.
1418 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1419 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1420 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1421 * if the node is unused or a new id else. The caller is to delete this
1422 * array using decrRef() as it is no more needed.
1423 * \throw If the coordinates array is not set.
1424 * \throw If the nodal connectivity of cells is not defined.
1425 * \throw If the nodal connectivity includes an invalid id.
1427 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1428 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1429 * \sa computeNodeIdsAlg()
1431 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1434 int nbOfNodes=getNumberOfNodes();
1435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1436 ret->alloc(nbOfNodes,1);
1437 int *traducer=ret->getPointer();
1438 std::fill(traducer,traducer+nbOfNodes,-1);
1439 int nbOfCells=getNumberOfCells();
1440 const int *connIndex=_nodal_connec_index->getConstPointer();
1441 const int *conn=_nodal_connec->getConstPointer();
1442 for(int i=0;i<nbOfCells;i++)
1443 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1446 if(conn[j]<nbOfNodes)
1447 traducer[conn[j]]=1;
1450 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1451 throw INTERP_KERNEL::Exception(oss.str().c_str());
1454 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1455 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1460 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1461 * For each cell in \b this the number of nodes constituting cell is computed.
1462 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1463 * So for pohyhedrons some nodes can be counted several times in the returned result.
1465 * \return a newly allocated array
1467 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1469 checkConnectivityFullyDefined();
1470 int nbOfCells=getNumberOfCells();
1471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1472 ret->alloc(nbOfCells,1);
1473 int *retPtr=ret->getPointer();
1474 const int *conn=getNodalConnectivity()->getConstPointer();
1475 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1476 for(int i=0;i<nbOfCells;i++,retPtr++)
1478 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1479 *retPtr=connI[i+1]-connI[i]-1;
1481 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1487 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1488 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1490 * \return a newly allocated array
1492 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1494 checkConnectivityFullyDefined();
1495 int nbOfCells=getNumberOfCells();
1496 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1497 ret->alloc(nbOfCells,1);
1498 int *retPtr=ret->getPointer();
1499 const int *conn=getNodalConnectivity()->getConstPointer();
1500 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1501 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1503 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1504 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1510 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1511 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1512 * array mean that the corresponding old node is no more used.
1513 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1514 * this->getNumberOfNodes() before call of this method. The caller is to
1515 * delete this array using decrRef() as it is no more needed.
1516 * \throw If the coordinates array is not set.
1517 * \throw If the nodal connectivity of cells is not defined.
1518 * \throw If the nodal connectivity includes an invalid id.
1520 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1521 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1523 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1525 int newNbOfNodes=-1;
1526 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1527 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1532 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1533 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1535 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1540 return AreCellsEqual0(conn,connI,cell1,cell2);
1542 return AreCellsEqual1(conn,connI,cell1,cell2);
1544 return AreCellsEqual2(conn,connI,cell1,cell2);
1546 return AreCellsEqual3(conn,connI,cell1,cell2);
1548 return AreCellsEqual7(conn,connI,cell1,cell2);
1550 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1554 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1556 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1558 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1559 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1564 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1566 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1568 int sz=connI[cell1+1]-connI[cell1];
1569 if(sz==connI[cell2+1]-connI[cell2])
1571 if(conn[connI[cell1]]==conn[connI[cell2]])
1573 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1574 unsigned dim=cm.getDimension();
1580 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1581 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1582 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1583 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1584 return work!=tmp+sz1?1:0;
1587 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1590 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1597 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1599 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1601 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1603 if(conn[connI[cell1]]==conn[connI[cell2]])
1605 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1606 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1614 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1616 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1618 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1620 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1621 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1628 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1630 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1632 int sz=connI[cell1+1]-connI[cell1];
1633 if(sz==connI[cell2+1]-connI[cell2])
1635 if(conn[connI[cell1]]==conn[connI[cell2]])
1637 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1638 unsigned dim=cm.getDimension();
1644 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1645 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1646 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1647 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1652 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1653 std::reverse_iterator<int *> it2((int *)tmp);
1654 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1660 return work!=tmp+sz1?1:0;
1663 {//case of SEG2 and SEG3
1664 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1666 if(!cm.isQuadratic())
1668 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1669 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1670 if(std::equal(it1,it2,conn+connI[cell2]+1))
1676 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])
1683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1691 * This method compares 2 cells coming from two unstructured meshes : \a this and \a other.
1692 * This method compares 2 cells having the same id 'cellId' in \a this and \a other.
1694 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1696 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1698 std::vector<int> c1,c2;
1699 getNodeIdsOfCell(cellId,c1);
1700 other->getNodeIdsOfCell(cellId,c2);
1701 std::size_t sz=c1.size();
1704 for(std::size_t i=0;i<sz;i++)
1706 std::vector<double> n1,n2;
1707 getCoordinatesOfNode(c1[0],n1);
1708 other->getCoordinatesOfNode(c2[0],n2);
1709 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1710 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1711 if(*std::max_element(n1.begin(),n1.end())>prec)
1718 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1719 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1720 * and result remains unchanged.
1721 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1722 * If in 'candidates' pool -1 value is considered as an empty value.
1723 * WARNING this method returns only ONE set of result !
1725 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1727 if(candidates.size()<1)
1730 std::vector<int>::const_iterator iter=candidates.begin();
1731 int start=(*iter++);
1732 for(;iter!=candidates.end();iter++)
1734 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1739 result->pushBackSilent(start);
1743 result->pushBackSilent(*iter);
1745 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1752 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1753 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1755 * \param [in] compType input specifying the technique used to compare cells each other.
1756 * - 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.
1757 * - 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)
1758 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1759 * - 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
1760 * can be used for users not sensitive to orientation of cell
1761 * \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.
1762 * \param [out] commonCells
1763 * \param [out] commonCellsI
1764 * \return the correspondance array old to new in a newly allocated array.
1767 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1769 checkConnectivityFullyDefined();
1770 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1771 getReverseNodalConnectivity(revNodal,revNodalI);
1772 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1775 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1776 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1778 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1779 int nbOfCells=nodalI->getNumberOfTuples()-1;
1780 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1781 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1782 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1783 std::vector<bool> isFetched(nbOfCells,false);
1786 for(int i=0;i<nbOfCells;i++)
1790 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1791 std::vector<int> v,v2;
1792 if(connOfNode!=connPtr+connIPtr[i+1])
1794 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1795 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1798 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1802 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1803 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1804 v2.resize(std::distance(v2.begin(),it));
1808 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1810 int pos=commonCellsI->back();
1811 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1812 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1813 isFetched[*it]=true;
1821 for(int i=startCellId;i<nbOfCells;i++)
1825 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1826 std::vector<int> v,v2;
1827 if(connOfNode!=connPtr+connIPtr[i+1])
1829 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1832 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1836 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1837 v2.resize(std::distance(v2.begin(),it));
1841 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1843 int pos=commonCellsI->back();
1844 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1845 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1846 isFetched[*it]=true;
1852 commonCellsArr=commonCells.retn();
1853 commonCellsIArr=commonCellsI.retn();
1857 * Removes duplicates of cells from \a this mesh and returns an array mapping between
1858 * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1859 * equal cells found.
1860 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1861 * to write this mesh to the MED file, its cells must be sorted using
1862 * sortCellsInMEDFileFrmt().
1863 * \param [in] compType - specifies a cell comparison technique. Meaning of its
1864 * valid values [0,1,2] is as follows.
1865 * - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1866 * connectivity and type. This is the strongest policy.
1867 * - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1868 * are based on same nodes and have the same type and orientation.
1869 * - 2 : "nodal". Two cells are considered equal \c iff they
1870 * are based on same nodes and have the same type. This is the weakest
1871 * policy, it can be used by users not sensitive to cell orientation.
1872 * \param [in] startCellId - specifies the cell id at which search for equal cells
1873 * starts. By default it is 0, which means that all cells in \a this will be
1875 * \return DataArrayInt - a new instance of DataArrayInt, of length \a
1876 * this->getNumberOfCells() before call of this method. The caller is to
1877 * delete this array using decrRef() as it is no more needed.
1878 * \throw If the coordinates array is not set.
1879 * \throw If the nodal connectivity of cells is not defined.
1880 * \throw If the nodal connectivity includes an invalid id.
1882 * \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1883 * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1885 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1887 DataArrayInt *commonCells=0,*commonCellsI=0;
1888 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1889 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1890 int newNbOfCells=-1;
1891 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1892 commonCellsI->end(),newNbOfCells);
1893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1894 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1895 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1900 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1901 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1902 * than \a other->getNumberOfCells() in the returned array means that there is no
1903 * corresponding cell in \a this mesh.
1904 * It is expected that \a this and \a other meshes share the same node coordinates
1905 * array, if it is not so an exception is thrown.
1906 * \param [in] other - the mesh to compare with.
1907 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1908 * valid values [0,1,2], see zipConnectivityTraducer().
1909 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1910 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1911 * values. The caller is to delete this array using
1912 * decrRef() as it is no more needed.
1913 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1916 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1917 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1918 * \sa checkDeepEquivalOnSameNodesWith()
1919 * \sa checkGeoEquivalWith()
1921 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1923 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1924 int nbOfCells=getNumberOfCells();
1925 static const int possibleCompType[]={0,1,2};
1926 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1928 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1929 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1931 throw INTERP_KERNEL::Exception(oss.str().c_str());
1933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1934 arr=o2n->substr(nbOfCells);
1935 arr->setName(other->getName());
1937 if(other->getNumberOfCells()==0)
1939 return arr->getMaxValue(tmp)<nbOfCells;
1943 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1944 * This method tries to determine if \b other is fully included in \b this.
1945 * The main difference is that this method is not expected to throw exception.
1946 * This method has two outputs :
1948 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1949 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1951 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1953 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1954 DataArrayInt *commonCells=0,*commonCellsI=0;
1955 int thisNbCells=getNumberOfCells();
1956 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1957 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1958 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1959 int otherNbCells=other->getNumberOfCells();
1960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1961 arr2->alloc(otherNbCells,1);
1962 arr2->fillWithZero();
1963 int *arr2Ptr=arr2->getPointer();
1964 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1965 for(int i=0;i<nbOfCommon;i++)
1967 int start=commonCellsPtr[commonCellsIPtr[i]];
1968 if(start<thisNbCells)
1970 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1972 int sig=commonCellsPtr[j]>0?1:-1;
1973 int val=std::abs(commonCellsPtr[j])-1;
1974 if(val>=thisNbCells)
1975 arr2Ptr[val-thisNbCells]=sig*(start+1);
1979 arr2->setName(other->getName());
1980 if(arr2->presenceOfValue(0))
1987 * Merges nodes equal within \a precision and returns an array describing the
1988 * permutation used to remove duplicate nodes.
1989 * \param [in] precision - minimal absolute distance between two nodes at which they are
1990 * considered not coincident.
1991 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1992 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1993 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1994 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1995 * is to delete this array using decrRef() as it is no more needed.
1996 * \throw If the coordinates array is not set.
1997 * \throw If the nodal connectivity of cells is not defined.
1999 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
2000 * \ref py_mcumesh_mergeNodes "Here is a Python example".
2002 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
2004 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2006 renumberNodes(ret->getConstPointer(),newNbOfNodes);
2012 * Merges nodes equal within \a precision and returns an array describing the
2013 * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
2014 * of merged nodes is changed to be at their barycenter.
2015 * \param [in] precision - minimal absolute distance between two nodes at which they are
2016 * considered not coincident.
2017 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
2018 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
2019 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
2020 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
2021 * is to delete this array using decrRef() as it is no more needed.
2022 * \throw If the coordinates array is not set.
2023 * \throw If the nodal connectivity of cells is not defined.
2025 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
2026 * \ref py_mcumesh_mergeNodes "Here is a Python example".
2028 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
2030 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2032 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
2037 * Substitutes node coordinates array of \a this mesh with that of \a other mesh
2038 * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
2039 * meshes match with a specified precision, else an exception is thrown and \a this
2040 * remains unchanged. In case of success the nodal connectivity of \a this mesh
2041 * is permuted according to new order of nodes.
2042 * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
2043 * coordinates (and so more expensive) than simple equality.
2044 * \param [in] other - the other mesh whose node coordinates array will be used by
2045 * \a this mesh in case of their equality.
2046 * \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
2047 * \throw If the coordinates array of \a this is not set.
2048 * \throw If the coordinates array of \a other is not set.
2049 * \throw If the coordinates of \a this and \a other do not match.
2051 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
2053 const DataArrayDouble *coords=other.getCoords();
2055 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
2057 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
2058 int otherNbOfNodes=other.getNumberOfNodes();
2059 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
2061 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
2062 setCoords(newCoords);
2063 bool areNodesMerged;
2065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
2068 setCoords(oldCoords);
2069 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
2071 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
2072 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
2073 if(pt!=da->getConstPointer()+da->getNbOfElems())
2075 setCoords(oldCoords);
2076 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
2078 setCoords(oldCoords);
2079 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
2084 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2085 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2086 * cellIds is not given explicitely but by a range python like.
2088 * \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.
2089 * \return a newly allocated
2091 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2092 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2094 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
2096 if(getMeshDimension()!=-1)
2098 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
2105 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2107 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2109 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2111 return const_cast<MEDCouplingUMesh *>(this);
2116 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2117 * The result mesh shares or not the node coordinates array with \a this mesh depending
2118 * on \a keepCoords parameter.
2119 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2120 * to write this mesh to the MED file, its cells must be sorted using
2121 * sortCellsInMEDFileFrmt().
2122 * \param [in] begin - an array of cell ids to include to the new mesh.
2123 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2124 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2125 * array of \a this mesh, else "free" nodes are removed from the result mesh
2126 * by calling zipCoords().
2127 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2128 * to delete this mesh using decrRef() as it is no more needed.
2129 * \throw If the coordinates array is not set.
2130 * \throw If the nodal connectivity of cells is not defined.
2131 * \throw If any cell id in the array \a begin is not valid.
2133 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2134 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2136 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2138 if(getMeshDimension()!=-1)
2140 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
2148 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2150 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2152 return const_cast<MEDCouplingUMesh *>(this);
2157 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2159 * 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.
2160 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2161 * The number of cells of \b this will remain the same with this method.
2163 * \param [in] begin begin of cell ids (included) of cells in this to assign
2164 * \param [in] end end of cell ids (excluded) of cells in this to assign
2165 * \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).
2166 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2168 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2170 checkConnectivityFullyDefined();
2171 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2172 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2173 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2174 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2176 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2177 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2178 throw INTERP_KERNEL::Exception(oss.str().c_str());
2180 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2181 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2183 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2184 throw INTERP_KERNEL::Exception(oss.str().c_str());
2186 int nbOfCells=getNumberOfCells();
2187 bool easyAssign=true;
2188 const int *connI=_nodal_connec_index->getConstPointer();
2189 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2190 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2192 if(*it>=0 && *it<nbOfCells)
2194 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2198 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2199 throw INTERP_KERNEL::Exception(oss.str().c_str());
2204 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2209 DataArrayInt *arrOut=0,*arrIOut=0;
2210 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2213 setConnectivity(arrOut,arrIOut,true);
2217 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2219 checkConnectivityFullyDefined();
2220 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2221 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2222 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2223 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2225 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2226 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2227 throw INTERP_KERNEL::Exception(oss.str().c_str());
2229 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2230 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2232 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2233 throw INTERP_KERNEL::Exception(oss.str().c_str());
2235 int nbOfCells=getNumberOfCells();
2236 bool easyAssign=true;
2237 const int *connI=_nodal_connec_index->getConstPointer();
2238 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2240 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2242 if(it>=0 && it<nbOfCells)
2244 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2248 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2249 throw INTERP_KERNEL::Exception(oss.str().c_str());
2254 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2259 DataArrayInt *arrOut=0,*arrIOut=0;
2260 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2263 setConnectivity(arrOut,arrIOut,true);
2268 * Finds cells whose all nodes are in a given array of node ids.
2269 * \param [in] partBg - the array of node ids.
2270 * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2271 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2272 * cells. The caller is to delete this array using decrRef() as it is no
2274 * \throw If the coordinates array is not set.
2275 * \throw If the nodal connectivity of cells is not defined.
2276 * \throw If any cell id in \a partBg is not valid.
2278 * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2279 * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2281 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2283 DataArrayInt *cellIdsKept=0;
2284 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2285 cellIdsKept->setName(getName());
2290 * Keeps from \a this only cells which constituing point id are in the ids specified by ['begin','end').
2291 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2292 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2293 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2295 * \param [in] begin input start of array of node ids.
2296 * \param [in] end input end of array of node ids.
2297 * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
2298 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2300 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2303 checkConnectivityFullyDefined();
2305 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2306 std::vector<bool> fastFinder(sz,false);
2307 for(const int *work=begin;work!=end;work++)
2308 if(*work>=0 && *work<sz)
2309 fastFinder[*work]=true;
2310 int nbOfCells=getNumberOfCells();
2311 const int *conn=getNodalConnectivity()->getConstPointer();
2312 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2313 for(int i=0;i<nbOfCells;i++)
2315 int ref=0,nbOfHit=0;
2316 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2320 if(fastFinder[*work2])
2323 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2324 cellIdsKept->pushBackSilent(i);
2326 cellIdsKeptArr=cellIdsKept.retn();
2330 * Finds cells whose all or some nodes are in a given array of node ids.
2331 * \param [in] begin - the array of node ids.
2332 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2333 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2334 * array \a begin are returned only, else cells whose any node is in the
2335 * array \a begin are returned.
2336 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2337 * cells. The caller is to delete this array using decrRef() as it is no more
2339 * \throw If the coordinates array is not set.
2340 * \throw If the nodal connectivity of cells is not defined.
2341 * \throw If any cell id in \a begin is not valid.
2343 * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2344 * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2346 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2348 DataArrayInt *cellIdsKept=0;
2349 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2350 cellIdsKept->setName(getName());
2355 Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
2356 copy are selected basing on specified node ids and the value of \a fullyIn
2357 parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the
2358 array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
2359 node is in the array of node ids. The created mesh shares the node coordinates array
2361 * \param [in] begin - the array of node ids.
2362 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2363 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2364 * array \a begin are copied, else cells whose any node is in the
2365 * array \a begin are copied.
2366 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2367 * to delete this mesh using decrRef() as it is no more needed.
2368 * \throw If the coordinates array is not set.
2369 * \throw If the nodal connectivity of cells is not defined.
2370 * \throw If any node id in \a begin is not valid.
2372 * \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
2373 * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
2375 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2377 DataArrayInt *cellIdsKept=0;
2378 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2380 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2384 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2385 * this->getMeshDimension(), that bound some cells of \a this mesh.
2386 * The cells of lower dimension to include to the result mesh are selected basing on
2387 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2388 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2389 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2390 * created mesh shares the node coordinates array with \a this mesh.
2391 * \param [in] begin - the array of node ids.
2392 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2393 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2394 * array \a begin are added, else cells whose any node is in the
2395 * array \a begin are added.
2396 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2397 * to delete this mesh using decrRef() as it is no more needed.
2398 * \throw If the coordinates array is not set.
2399 * \throw If the nodal connectivity of cells is not defined.
2400 * \throw If any node id in \a begin is not valid.
2402 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2403 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2405 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2408 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2409 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2410 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2411 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2415 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2416 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2417 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2418 * array of \a this mesh, else "free" nodes are removed from the result mesh
2419 * by calling zipCoords().
2420 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2421 * to delete this mesh using decrRef() as it is no more needed.
2422 * \throw If the coordinates array is not set.
2423 * \throw If the nodal connectivity of cells is not defined.
2425 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2426 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2428 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2430 DataArrayInt *desc=DataArrayInt::New();
2431 DataArrayInt *descIndx=DataArrayInt::New();
2432 DataArrayInt *revDesc=DataArrayInt::New();
2433 DataArrayInt *revDescIndx=DataArrayInt::New();
2435 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2438 descIndx->decrRef();
2439 int nbOfCells=meshDM1->getNumberOfCells();
2440 const int *revDescIndxC=revDescIndx->getConstPointer();
2441 std::vector<int> boundaryCells;
2442 for(int i=0;i<nbOfCells;i++)
2443 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2444 boundaryCells.push_back(i);
2445 revDescIndx->decrRef();
2446 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2451 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2452 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2453 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2455 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2457 checkFullyDefined();
2458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2463 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2464 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2467 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2468 const int *revDescPtr=revDesc->getConstPointer();
2469 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2470 int nbOfCells=getNumberOfCells();
2471 std::vector<bool> ret1(nbOfCells,false);
2473 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2474 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2475 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2477 DataArrayInt *ret2=DataArrayInt::New();
2479 int *ret2Ptr=ret2->getPointer();
2481 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2484 ret2->setName("BoundaryCells");
2489 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2490 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2491 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2492 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2494 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2495 * This method method returns cells ids set s = s1 + s2 where :
2497 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2498 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2500 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2501 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2503 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2504 * \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
2505 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2507 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2509 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2510 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2511 checkConnectivityFullyDefined();
2512 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2513 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2514 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2516 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2517 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2519 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2520 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2521 DataArrayInt *idsOtherInConsti=0;
2522 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2525 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2527 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2528 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2529 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2531 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2532 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2534 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2535 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2536 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2537 neighThisPartAuto=0;
2538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2539 const int li[2]={0,1};
2540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2541 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2542 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2545 cellIdsRk0=s0arr.retn();
2546 cellIdsRk1=s_renum1.retn();
2550 * 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
2551 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2553 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2555 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2562 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2563 revDesc=0; desc=0; descIndx=0;
2564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2565 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2566 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2570 * Finds nodes lying on the boundary of \a this mesh.
2571 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2572 * nodes. The caller is to delete this array using decrRef() as it is no
2574 * \throw If the coordinates array is not set.
2575 * \throw If the nodal connectivity of cells is node defined.
2577 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2578 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2580 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2582 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2583 return skin->computeFetchedNodeIds();
2586 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2589 return const_cast<MEDCouplingUMesh *>(this);
2593 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2594 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
2595 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2596 * array is modified accordingly.
2597 * \param [in] newNodeNumbers - a permutation array, of length \a
2598 * this->getNumberOfNodes(), in "Old to New" mode.
2599 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2600 * \param [in] newNbOfNodes - number of nodes remaining after renumbering.
2601 * \throw If the coordinates array is not set.
2602 * \throw If the nodal connectivity of cells is not defined.
2604 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2605 * \ref py_mcumesh_renumberNodes "Here is a Python example".
2607 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2609 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2610 renumberNodesInConn(newNodeNumbers);
2614 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2615 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
2616 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2617 * array is modified accordingly. In contrast to renumberNodes(), location
2618 * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
2619 * \param [in] newNodeNumbers - a permutation array, of length \a
2620 * this->getNumberOfNodes(), in "Old to New" mode.
2621 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2622 * \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
2623 * actually one more than the maximal id in \a newNodeNumbers.
2624 * \throw If the coordinates array is not set.
2625 * \throw If the nodal connectivity of cells is not defined.
2627 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2628 * \ref py_mcumesh_renumberNodes "Here is a Python example".
2630 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2632 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2633 renumberNodesInConn(newNodeNumbers);
2637 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2638 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2639 * 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.
2640 * 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.
2641 * 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.
2643 * \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
2644 * parameter is altered during the call.
2645 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2646 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2647 * \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.
2649 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2651 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2652 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2654 checkFullyDefined();
2655 otherDimM1OnSameCoords.checkFullyDefined();
2656 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2657 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2658 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2659 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2660 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2661 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2664 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2665 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2669 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2671 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2672 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2673 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2674 DataArrayInt *idsTmp=0;
2675 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2679 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2680 DataArrayInt *tmp0=0,*tmp1=0;
2681 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2682 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2686 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2687 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2689 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2690 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2691 nodeIdsToDuplicate=s3.retn();
2695 * This method operates a modification of the connectivity and coords in \b this.
2696 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2697 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2698 * 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
2699 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2700 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2702 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2704 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2705 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2707 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2709 int nbOfNodes=getNumberOfNodes();
2710 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2711 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2715 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2716 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2717 * This method is a generalization of shiftNodeNumbersInConn().
2718 * \warning This method performs no check of validity of new ids. **Use it with care !**
2719 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2720 * this->getNumberOfNodes(), in "Old to New" mode.
2721 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2722 * \throw If the nodal connectivity of cells is not defined.
2724 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2725 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2727 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2729 checkConnectivityFullyDefined();
2730 int *conn=getNodalConnectivity()->getPointer();
2731 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2732 int nbOfCells=getNumberOfCells();
2733 for(int i=0;i<nbOfCells;i++)
2734 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2736 int& node=conn[iconn];
2737 if(node>=0)//avoid polyhedron separator
2739 node=newNodeNumbersO2N[node];
2742 _nodal_connec->declareAsNew();
2747 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2748 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2749 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2751 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2753 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2755 checkConnectivityFullyDefined();
2756 int *conn=getNodalConnectivity()->getPointer();
2757 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2758 int nbOfCells=getNumberOfCells();
2759 for(int i=0;i<nbOfCells;i++)
2760 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2762 int& node=conn[iconn];
2763 if(node>=0)//avoid polyhedron separator
2768 _nodal_connec->declareAsNew();
2773 * This method operates a modification of the connectivity in \b this.
2774 * 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.
2775 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2776 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2777 * 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
2778 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2779 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2781 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2782 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2784 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2785 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2786 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2788 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2790 checkConnectivityFullyDefined();
2791 std::map<int,int> m;
2793 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2795 int *conn=getNodalConnectivity()->getPointer();
2796 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2797 int nbOfCells=getNumberOfCells();
2798 for(int i=0;i<nbOfCells;i++)
2799 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2801 int& node=conn[iconn];
2802 if(node>=0)//avoid polyhedron separator
2804 std::map<int,int>::iterator it=m.find(node);
2813 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2815 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2816 * After the call of this method the number of cells remains the same as before.
2818 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2819 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2820 * be strictly in [0;this->getNumberOfCells()).
2822 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2823 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2824 * should be contained in[0;this->getNumberOfCells()).
2826 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2828 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2830 checkConnectivityFullyDefined();
2831 int nbCells=getNumberOfCells();
2832 const int *array=old2NewBg;
2834 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2836 const int *conn=_nodal_connec->getConstPointer();
2837 const int *connI=_nodal_connec_index->getConstPointer();
2838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2840 const int *n2oPtr=n2o->begin();
2841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2842 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2843 newConn->copyStringInfoFrom(*_nodal_connec);
2844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2845 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2846 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2848 int *newC=newConn->getPointer();
2849 int *newCI=newConnI->getPointer();
2852 for(int i=0;i<nbCells;i++)
2855 int nbOfElts=connI[pos+1]-connI[pos];
2856 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2861 setConnectivity(newConn,newConnI);
2863 free(const_cast<int *>(array));
2867 * Finds cells whose bounding boxes intersect a given bounding box.
2868 * \param [in] bbox - an array defining the bounding box via coordinates of its
2869 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2871 * \param [in] eps - a factor used to increase size of the bounding box of cell
2872 * before comparing it with \a bbox. This factor is multiplied by the maximal
2873 * extent of the bounding box of cell to produce an addition to this bounding box.
2874 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2875 * cells. The caller is to delete this array using decrRef() as it is no more
2877 * \throw If the coordinates array is not set.
2878 * \throw If the nodal connectivity of cells is not defined.
2880 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2881 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2883 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2886 if(getMeshDimension()==-1)
2888 elems->pushBackSilent(0);
2889 return elems.retn();
2891 int dim=getSpaceDimension();
2892 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2893 const int* conn = getNodalConnectivity()->getConstPointer();
2894 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2895 const double* coords = getCoords()->getConstPointer();
2896 int nbOfCells=getNumberOfCells();
2897 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2899 for (int i=0; i<dim; i++)
2901 elem_bb[i*2]=std::numeric_limits<double>::max();
2902 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2905 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2907 int node= conn[inode];
2908 if(node>=0)//avoid polyhedron separator
2910 for (int idim=0; idim<dim; idim++)
2912 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2914 elem_bb[idim*2] = coords[node*dim+idim] ;
2916 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2918 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2923 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2924 elems->pushBackSilent(ielem);
2926 return elems.retn();
2930 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2931 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2932 * added in 'elems' parameter.
2934 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2937 if(getMeshDimension()==-1)
2939 elems->pushBackSilent(0);
2940 return elems.retn();
2942 int dim=getSpaceDimension();
2943 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2944 const int* conn = getNodalConnectivity()->getConstPointer();
2945 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2946 const double* coords = getCoords()->getConstPointer();
2947 int nbOfCells=getNumberOfCells();
2948 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2950 for (int i=0; i<dim; i++)
2952 elem_bb[i*2]=std::numeric_limits<double>::max();
2953 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2956 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2958 int node= conn[inode];
2959 if(node>=0)//avoid polyhedron separator
2961 for (int idim=0; idim<dim; idim++)
2963 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2965 elem_bb[idim*2] = coords[node*dim+idim] ;
2967 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2969 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2974 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2975 elems->pushBackSilent(ielem);
2977 return elems.retn();
2981 * Returns a type of a cell by its id.
2982 * \param [in] cellId - the id of the cell of interest.
2983 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2984 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2986 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2988 const int *ptI=_nodal_connec_index->getConstPointer();
2989 const int *pt=_nodal_connec->getConstPointer();
2990 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2991 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2994 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2995 throw INTERP_KERNEL::Exception(oss.str().c_str());
3000 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
3001 * This method does not throw exception if geometric type \a type is not in \a this.
3002 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
3003 * The coordinates array is not considered here.
3005 * \param [in] type the geometric type
3006 * \return cell ids in this having geometric type \a type.
3008 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
3011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
3013 checkConnectivityFullyDefined();
3014 int nbCells=getNumberOfCells();
3015 int mdim=getMeshDimension();
3016 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
3017 if(mdim!=(int)cm.getDimension())
3018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
3019 const int *ptI=_nodal_connec_index->getConstPointer();
3020 const int *pt=_nodal_connec->getConstPointer();
3021 for(int i=0;i<nbCells;i++)
3023 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
3024 ret->pushBackSilent(i);
3030 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
3032 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3034 const int *ptI=_nodal_connec_index->getConstPointer();
3035 const int *pt=_nodal_connec->getConstPointer();
3036 int nbOfCells=getNumberOfCells();
3038 for(int i=0;i<nbOfCells;i++)
3039 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3045 * Returns the nodal connectivity of a given cell.
3046 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3047 * all returned node ids can be used in getCoordinatesOfNode().
3048 * \param [in] cellId - an id of the cell of interest.
3049 * \param [in,out] conn - a vector where the node ids are appended. It is not
3050 * cleared before the appending.
3051 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3053 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3055 const int *ptI=_nodal_connec_index->getConstPointer();
3056 const int *pt=_nodal_connec->getConstPointer();
3057 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3062 std::string MEDCouplingUMesh::simpleRepr() const
3064 static const char msg0[]="No coordinates specified !";
3065 std::ostringstream ret;
3066 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3067 ret << "Description of mesh : \"" << getDescription() << "\"\n";
3069 double tt=getTime(tmpp1,tmpp2);
3070 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3071 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
3073 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3075 { ret << " Mesh dimension has not been set or is invalid !"; }
3078 const int spaceDim=getSpaceDimension();
3079 ret << spaceDim << "\nInfo attached on space dimension : ";
3080 for(int i=0;i<spaceDim;i++)
3081 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3085 ret << msg0 << "\n";
3086 ret << "Number of nodes : ";
3088 ret << getNumberOfNodes() << "\n";
3090 ret << msg0 << "\n";
3091 ret << "Number of cells : ";
3092 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3093 ret << getNumberOfCells() << "\n";
3095 ret << "No connectivity specified !" << "\n";
3096 ret << "Cell types present : ";
3097 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3099 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3100 ret << cm.getRepr() << " ";
3106 std::string MEDCouplingUMesh::advancedRepr() const
3108 std::ostringstream ret;
3109 ret << simpleRepr();
3110 ret << "\nCoordinates array : \n___________________\n\n";
3112 _coords->reprWithoutNameStream(ret);
3114 ret << "No array set !\n";
3115 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3116 reprConnectivityOfThisLL(ret);
3121 * This method returns a C++ code that is a dump of \a this.
3122 * This method will throw if this is not fully defined.
3124 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
3126 static const char coordsName[]="coords";
3127 static const char connName[]="conn";
3128 static const char connIName[]="connI";
3129 checkFullyDefined();
3130 std::ostringstream ret; ret << "// coordinates" << std::endl;
3131 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3132 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3133 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3134 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3135 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3136 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3137 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3141 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3143 std::ostringstream ret;
3144 reprConnectivityOfThisLL(ret);
3149 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3150 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3151 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3154 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3155 * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
3156 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3158 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
3160 int mdim=getMeshDimension();
3162 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3163 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3165 bool needToCpyCT=true;
3168 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3176 if(!_nodal_connec_index)
3178 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3183 tmp2=_nodal_connec_index;
3186 ret->setConnectivity(tmp1,tmp2,false);
3191 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3192 ret->setCoords(coords);
3195 ret->setCoords(_coords);
3199 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3201 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3203 int nbOfCells=getNumberOfCells();
3204 const int *c=_nodal_connec->getConstPointer();
3205 const int *ci=_nodal_connec_index->getConstPointer();
3206 for(int i=0;i<nbOfCells;i++)
3208 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3209 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3210 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3215 stream << "Connectivity not defined !\n";
3218 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3220 const int *ptI=_nodal_connec_index->getConstPointer();
3221 const int *pt=_nodal_connec->getConstPointer();
3222 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3223 return ptI[cellId+1]-ptI[cellId]-1;
3225 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3229 * Returns types of cells of the specified part of \a this mesh.
3230 * This method avoids computing sub-mesh explicitely to get its types.
3231 * \param [in] begin - an array of cell ids of interest.
3232 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3233 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3234 * describing the cell types.
3235 * \throw If the coordinates array is not set.
3236 * \throw If the nodal connectivity of cells is not defined.
3239 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
3241 checkFullyDefined();
3242 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3243 const int *conn=_nodal_connec->getConstPointer();
3244 const int *connIndex=_nodal_connec_index->getConstPointer();
3245 for(const int *w=begin;w!=end;w++)
3246 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3251 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3252 * a set of types of cells constituting \a this mesh.
3253 * This method is for advanced users having prepared their connectivity before. For
3254 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3255 * \param [in] conn - the nodal connectivity array.
3256 * \param [in] connIndex - the nodal connectivity index array.
3257 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3260 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3262 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3263 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3264 if(isComputingTypes)
3270 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3271 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3273 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3274 _nodal_connec(0),_nodal_connec_index(0),
3275 _types(other._types)
3277 if(other._nodal_connec)
3278 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3279 if(other._nodal_connec_index)
3280 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3283 MEDCouplingUMesh::~MEDCouplingUMesh()
3286 _nodal_connec->decrRef();
3287 if(_nodal_connec_index)
3288 _nodal_connec_index->decrRef();
3292 * Recomputes a set of cell types of \a this mesh. For more info see
3293 * \ref MEDCouplingUMeshNodalConnectivity.
3295 void MEDCouplingUMesh::computeTypes()
3297 if(_nodal_connec && _nodal_connec_index)
3300 const int *conn=_nodal_connec->getConstPointer();
3301 const int *connIndex=_nodal_connec_index->getConstPointer();
3302 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3304 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3305 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3310 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3312 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3314 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3315 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3319 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3321 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3323 if(!_nodal_connec_index || !_nodal_connec)
3324 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3328 * Returns a number of cells constituting \a this mesh.
3329 * \return int - the number of cells in \a this mesh.
3330 * \throw If the nodal connectivity of cells is not defined.
3332 int MEDCouplingUMesh::getNumberOfCells() const
3334 if(_nodal_connec_index)
3335 return _nodal_connec_index->getNumberOfTuples()-1;
3340 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3344 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3345 * mesh. For more info see \ref MEDCouplingMeshesPage.
3346 * \return int - the dimension of \a this mesh.
3347 * \throw If the mesh dimension is not defined using setMeshDimension().
3349 int MEDCouplingUMesh::getMeshDimension() const
3352 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3357 * Returns a length of the nodal connectivity array.
3358 * This method is for test reason. Normally the integer returned is not useable by
3359 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3360 * \return int - the length of the nodal connectivity array.
3362 int MEDCouplingUMesh::getMeshLength() const
3364 return _nodal_connec->getNbOfElems();
3368 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3370 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3372 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3373 tinyInfo.push_back(getMeshDimension());
3374 tinyInfo.push_back(getNumberOfCells());
3376 tinyInfo.push_back(getMeshLength());
3378 tinyInfo.push_back(-1);
3382 * First step of unserialization process.
3384 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3386 return tinyInfo[6]<=0;
3390 * Second step of serialization process.
3391 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3393 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3395 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3397 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3401 * Third and final step of serialization process.
3403 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3405 MEDCouplingPointSet::serialize(a1,a2);
3406 if(getMeshDimension()>-1)
3408 a1=DataArrayInt::New();
3409 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3410 int *ptA1=a1->getPointer();
3411 const int *conn=getNodalConnectivity()->getConstPointer();
3412 const int *index=getNodalConnectivityIndex()->getConstPointer();
3413 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3414 std::copy(conn,conn+getMeshLength(),ptA1);
3421 * Second and final unserialization process.
3422 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3424 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3426 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3427 setMeshDimension(tinyInfo[5]);
3431 const int *recvBuffer=a1->getConstPointer();
3432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3433 myConnecIndex->alloc(tinyInfo[6]+1,1);
3434 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3436 myConnec->alloc(tinyInfo[7],1);
3437 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3438 setConnectivity(myConnec, myConnecIndex);
3443 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3444 * CellIds are given using range specified by a start an end and step.
3446 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3448 checkFullyDefined();
3449 int ncell=getNumberOfCells();
3450 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3451 ret->_mesh_dim=_mesh_dim;
3452 ret->setCoords(_coords);
3453 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3455 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3457 const int *conn=_nodal_connec->getConstPointer();
3458 const int *connIndex=_nodal_connec_index->getConstPointer();
3459 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3461 if(work>=0 && work<ncell)
3463 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3467 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3468 throw INTERP_KERNEL::Exception(oss.str().c_str());
3471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3472 int *newConnPtr=newConn->getPointer();
3473 std::set<INTERP_KERNEL::NormalizedCellType> types;
3475 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3477 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3478 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3480 ret->setConnectivity(newConn,newConnI,false);
3482 ret->copyTinyInfoFrom(this);
3487 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3488 * Keeps from \a this only cells which constituing point id are in the ids specified by ['begin','end').
3489 * The return newly allocated mesh will share the same coordinates as \a this.
3491 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3493 checkFullyDefined();
3494 int ncell=getNumberOfCells();
3495 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3496 ret->_mesh_dim=_mesh_dim;
3497 ret->setCoords(_coords);
3498 std::size_t nbOfElemsRet=std::distance(begin,end);
3499 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3501 const int *conn=_nodal_connec->getConstPointer();
3502 const int *connIndex=_nodal_connec_index->getConstPointer();
3504 for(const int *work=begin;work!=end;work++,newNbring++)
3506 if(*work>=0 && *work<ncell)
3507 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3511 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3512 throw INTERP_KERNEL::Exception(oss.str().c_str());
3515 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3516 int *connRetWork=connRet;
3517 std::set<INTERP_KERNEL::NormalizedCellType> types;
3518 for(const int *work=begin;work!=end;work++)
3520 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3521 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3524 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3525 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3526 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3527 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3529 ret->copyTinyInfoFrom(this);
3534 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3536 * For 1D cells, the returned field contains lengths.<br>
3537 * For 2D cells, the returned field contains areas.<br>
3538 * For 3D cells, the returned field contains volumes.
3539 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3540 * orientation, i.e. the volume is always positive.
3541 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3542 * and one time . The caller is to delete this field using decrRef() as it is no
3545 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3547 std::string name="MeasureOfMesh_";
3549 int nbelem=getNumberOfCells();
3550 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3551 field->setName(name.c_str());
3552 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3553 array->alloc(nbelem,1);
3554 double *area_vol=array->getPointer();
3555 field->setArray(array) ; array=0;
3556 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3557 field->synchronizeTimeWithMesh();
3558 if(getMeshDimension()!=-1)
3561 INTERP_KERNEL::NormalizedCellType type;
3562 int dim_space=getSpaceDimension();
3563 const double *coords=getCoords()->getConstPointer();
3564 const int *connec=getNodalConnectivity()->getConstPointer();
3565 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3566 for(int iel=0;iel<nbelem;iel++)
3568 ipt=connec_index[iel];
3569 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3570 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);
3573 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3577 area_vol[0]=std::numeric_limits<double>::max();
3579 return field.retn();
3583 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3585 * For 1D cells, the returned array contains lengths.<br>
3586 * For 2D cells, the returned array contains areas.<br>
3587 * For 3D cells, the returned array contains volumes.
3588 * This method avoids building explicitly a part of \a this mesh to perform the work.
3589 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3590 * orientation, i.e. the volume is always positive.
3591 * \param [in] begin - an array of cell ids of interest.
3592 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3593 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3594 * delete this array using decrRef() as it is no more needed.
3596 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3597 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3598 * \sa getMeasureField()
3600 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3602 std::string name="PartMeasureOfMesh_";
3604 int nbelem=(int)std::distance(begin,end);
3605 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3606 array->setName(name.c_str());
3607 array->alloc(nbelem,1);
3608 double *area_vol=array->getPointer();
3609 if(getMeshDimension()!=-1)
3612 INTERP_KERNEL::NormalizedCellType type;
3613 int dim_space=getSpaceDimension();
3614 const double *coords=getCoords()->getConstPointer();
3615 const int *connec=getNodalConnectivity()->getConstPointer();
3616 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3617 for(const int *iel=begin;iel!=end;iel++)
3619 ipt=connec_index[*iel];
3620 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3621 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3624 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3628 area_vol[0]=std::numeric_limits<double>::max();
3630 return array.retn();
3634 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3635 * \a this one. The returned field contains the dual cell volume for each corresponding
3636 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3637 * the dual mesh in P1 sens of \a this.<br>
3638 * For 1D cells, the returned field contains lengths.<br>
3639 * For 2D cells, the returned field contains areas.<br>
3640 * For 3D cells, the returned field contains volumes.
3641 * This method is useful to check "P1*" conservative interpolators.
3642 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3643 * orientation, i.e. the volume is always positive.
3644 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3645 * nodes and one time. The caller is to delete this array using decrRef() as
3646 * it is no more needed.
3648 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3650 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3651 std::string name="MeasureOnNodeOfMesh_";
3653 int nbNodes=getNumberOfNodes();
3654 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3655 double cst=1./((double)getMeshDimension()+1.);
3656 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3657 array->alloc(nbNodes,1);
3658 double *valsToFill=array->getPointer();
3659 std::fill(valsToFill,valsToFill+nbNodes,0.);
3660 const double *values=tmp->getArray()->getConstPointer();
3661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3663 getReverseNodalConnectivity(da,daInd);
3664 const int *daPtr=da->getConstPointer();
3665 const int *daIPtr=daInd->getConstPointer();
3666 for(int i=0;i<nbNodes;i++)
3667 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3668 valsToFill[i]+=cst*values[*cell];
3670 ret->setArray(array);
3675 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3676 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3677 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3678 * and are normalized.
3679 * <br> \a this can be either
3680 * - a 2D mesh in 2D or 3D space or
3681 * - an 1D mesh in 2D space.
3683 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3684 * cells and one time. The caller is to delete this field using decrRef() as
3685 * it is no more needed.
3686 * \throw If the nodal connectivity of cells is not defined.
3687 * \throw If the coordinates array is not set.
3688 * \throw If the mesh dimension is not set.
3689 * \throw If the mesh and space dimension is not as specified above.
3691 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3693 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3694 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3695 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3696 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3697 int nbOfCells=getNumberOfCells();
3698 int nbComp=getMeshDimension()+1;
3699 array->alloc(nbOfCells,nbComp);
3700 double *vals=array->getPointer();
3701 const int *connI=_nodal_connec_index->getConstPointer();
3702 const int *conn=_nodal_connec->getConstPointer();
3703 const double *coords=_coords->getConstPointer();
3704 if(getMeshDimension()==2)
3706 if(getSpaceDimension()==3)
3708 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3709 const double *locPtr=loc->getConstPointer();
3710 for(int i=0;i<nbOfCells;i++,vals+=3)
3712 int offset=connI[i];
3713 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3714 double n=INTERP_KERNEL::norm<3>(vals);
3715 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3720 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3721 const double *isAbsPtr=isAbs->getArray()->begin();
3722 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3723 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3726 else//meshdimension==1
3729 for(int i=0;i<nbOfCells;i++)
3731 int offset=connI[i];
3732 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3733 double n=INTERP_KERNEL::norm<2>(tmp);
3734 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3739 ret->setArray(array);
3741 ret->synchronizeTimeWithSupport();
3746 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3747 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3748 * and are normalized.
3749 * <br> \a this can be either
3750 * - a 2D mesh in 2D or 3D space or
3751 * - an 1D mesh in 2D space.
3753 * This method avoids building explicitly a part of \a this mesh to perform the work.
3754 * \param [in] begin - an array of cell ids of interest.
3755 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3756 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3757 * cells and one time. The caller is to delete this field using decrRef() as
3758 * it is no more needed.
3759 * \throw If the nodal connectivity of cells is not defined.
3760 * \throw If the coordinates array is not set.
3761 * \throw If the mesh dimension is not set.
3762 * \throw If the mesh and space dimension is not as specified above.
3763 * \sa buildOrthogonalField()
3765 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3766 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3768 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3770 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3771 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3772 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3773 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3774 std::size_t nbelems=std::distance(begin,end);
3775 int nbComp=getMeshDimension()+1;
3776 array->alloc((int)nbelems,nbComp);
3777 double *vals=array->getPointer();
3778 const int *connI=_nodal_connec_index->getConstPointer();
3779 const int *conn=_nodal_connec->getConstPointer();
3780 const double *coords=_coords->getConstPointer();
3781 if(getMeshDimension()==2)
3783 if(getSpaceDimension()==3)
3785 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3786 const double *locPtr=loc->getConstPointer();
3787 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3789 int offset=connI[*i];
3790 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3791 double n=INTERP_KERNEL::norm<3>(vals);
3792 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3797 for(std::size_t i=0;i<nbelems;i++)
3798 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3801 else//meshdimension==1
3804 for(const int *i=begin;i!=end;i++)
3806 int offset=connI[*i];
3807 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3808 double n=INTERP_KERNEL::norm<2>(tmp);
3809 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3814 ret->setArray(array);
3816 ret->synchronizeTimeWithSupport();
3821 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3822 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3823 * and are \b not normalized.
3824 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3825 * cells and one time. The caller is to delete this field using decrRef() as
3826 * it is no more needed.
3827 * \throw If the nodal connectivity of cells is not defined.
3828 * \throw If the coordinates array is not set.
3829 * \throw If \a this->getMeshDimension() != 1.
3830 * \throw If \a this mesh includes cells of type other than SEG2.
3832 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3834 if(getMeshDimension()!=1)
3835 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3836 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3837 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3838 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3839 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3840 int nbOfCells=getNumberOfCells();
3841 int spaceDim=getSpaceDimension();
3842 array->alloc(nbOfCells,spaceDim);
3843 double *pt=array->getPointer();
3844 const double *coo=getCoords()->getConstPointer();
3845 std::vector<int> conn;
3847 for(int i=0;i<nbOfCells;i++)
3850 getNodeIdsOfCell(i,conn);
3851 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3853 ret->setArray(array);
3855 ret->synchronizeTimeWithSupport();
3860 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3861 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3862 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3863 * from. If a result face is shared by two 3D cells, then the face in included twice in
3865 * \param [in] origin - 3 components of a point defining location of the plane.
3866 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3867 * must be greater than 1e-6.
3868 * \param [in] eps - half-thickness of the plane.
3869 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3870 * producing correspondent 2D cells. The caller is to delete this array
3871 * using decrRef() as it is no more needed.
3872 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3873 * not share the node coordinates array with \a this mesh. The caller is to
3874 * delete this mesh using decrRef() as it is no more needed.
3875 * \throw If the coordinates array is not set.
3876 * \throw If the nodal connectivity of cells is not defined.
3877 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3878 * \throw If magnitude of \a vec is less than 1e-6.
3879 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3880 * \throw If \a this includes quadratic cells.
3882 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3884 checkFullyDefined();
3885 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3886 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3888 if(candidates->empty())
3889 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3890 std::vector<int> nodes;
3891 DataArrayInt *cellIds1D=0;
3892 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3893 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3898 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3899 revDesc2=0; revDescIndx2=0;
3900 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3901 revDesc1=0; revDescIndx1=0;
3902 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3903 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3905 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3906 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3908 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3909 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3910 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3911 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3912 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3914 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3915 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3916 if(cellIds2->empty())
3917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3918 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3919 ret->setCoords(mDesc1->getCoords());
3920 ret->setConnectivity(conn,connI,true);
3921 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3926 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3927 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
3928 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3930 * \param [in] origin - 3 components of a point defining location of the plane.
3931 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3932 * must be greater than 1e-6.
3933 * \param [in] eps - half-thickness of the plane.
3934 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3935 * producing correspondent segments. The caller is to delete this array
3936 * using decrRef() as it is no more needed.
3937 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3938 * mesh in 3D space. This mesh does not share the node coordinates array with
3939 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3941 * \throw If the coordinates array is not set.
3942 * \throw If the nodal connectivity of cells is not defined.
3943 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3944 * \throw If magnitude of \a vec is less than 1e-6.
3945 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3946 * \throw If \a this includes quadratic cells.
3948 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3950 checkFullyDefined();
3951 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3952 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3953 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3954 if(candidates->empty())
3955 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3956 std::vector<int> nodes;
3957 DataArrayInt *cellIds1D=0;
3958 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3959 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3964 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3965 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3966 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3968 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3969 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3971 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3972 int ncellsSub=subMesh->getNumberOfCells();
3973 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3974 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3975 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3976 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3979 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3980 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3981 for(int i=0;i<ncellsSub;i++)
3983 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3985 if(cut3DSurf[i].first!=-2)
3987 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3988 connI->pushBackSilent(conn->getNumberOfTuples());
3989 cellIds2->pushBackSilent(i);
3993 int cellId3DSurf=cut3DSurf[i].second;
3994 int offset=nodalI[cellId3DSurf]+1;
3995 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3996 for(int j=0;j<nbOfEdges;j++)
3998 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3999 connI->pushBackSilent(conn->getNumberOfTuples());
4000 cellIds2->pushBackSilent(cellId3DSurf);
4005 if(cellIds2->empty())
4006 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
4007 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
4008 ret->setCoords(mDesc1->getCoords());
4009 ret->setConnectivity(conn,connI,true);
4010 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
4015 * Finds cells whose bounding boxes intersect a given plane.
4016 * \param [in] origin - 3 components of a point defining location of the plane.
4017 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
4018 * must be greater than 1e-6.
4019 * \param [in] eps - half-thickness of the plane.
4020 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
4021 * cells. The caller is to delete this array using decrRef() as it is no more
4023 * \throw If the coordinates array is not set.
4024 * \throw If the nodal connectivity of cells is not defined.
4025 * \throw If \a this->getSpaceDimension() != 3.
4026 * \throw If magnitude of \a vec is less than 1e-6.
4027 * \sa buildSlice3D()
4029 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
4031 checkFullyDefined();
4032 if(getSpaceDimension()!=3)
4033 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4034 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4036 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4038 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4039 double angle=acos(vec[2]/normm);
4040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
4044 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
4045 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4046 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4048 mw->getBoundingBox(bbox);
4049 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4050 cellIds=mw->getCellsInBoundingBox(bbox,eps);
4054 getBoundingBox(bbox);
4055 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4056 cellIds=getCellsInBoundingBox(bbox,eps);
4058 return cellIds.retn();
4062 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4063 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4064 * No consideration of coordinate is done by this method.
4065 * 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)
4066 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
4068 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
4070 if(getMeshDimension()!=1)
4071 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4072 int nbCells=getNumberOfCells();
4074 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4075 const int *connI=_nodal_connec_index->getConstPointer();
4076 const int *conn=_nodal_connec->getConstPointer();
4077 int ref=conn[connI[0]+2];
4078 for(int i=1;i<nbCells;i++)
4080 if(conn[connI[i]+1]!=ref)
4082 ref=conn[connI[i]+2];
4088 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4089 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4090 * \param pt reference point of the line
4091 * \param v normalized director vector of the line
4092 * \param eps max precision before throwing an exception
4093 * \param res output of size this->getNumberOfCells
4095 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4097 if(getMeshDimension()!=1)
4098 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4099 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4100 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4101 if(getSpaceDimension()!=3)
4102 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4103 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4104 const double *fPtr=f->getArray()->getConstPointer();
4106 for(int i=0;i<getNumberOfCells();i++)
4108 const double *tmp1=fPtr+3*i;
4109 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4110 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4111 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4112 double n1=INTERP_KERNEL::norm<3>(tmp);
4113 n1/=INTERP_KERNEL::norm<3>(tmp1);
4115 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4117 const double *coo=getCoords()->getConstPointer();
4118 for(int i=0;i<getNumberOfNodes();i++)
4120 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4121 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4122 res[i]=std::accumulate(tmp,tmp+3,0.);
4127 * 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.
4128 * \a this is expected to be a mesh so that its space dimension is equal to its
4129 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4130 * 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).
4132 * 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
4133 * 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).
4134 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4136 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4137 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4139 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4140 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4141 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4142 * \return the positive value of the distance.
4143 * \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
4145 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4147 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
4149 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4150 if(meshDim!=spaceDim-1)
4151 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4152 if(meshDim!=2 && meshDim!=1)
4153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4154 checkFullyDefined();
4155 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4156 { 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()); }
4157 DataArrayInt *ret1=0;
4158 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4159 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4160 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4161 cellId=*ret1Safe->begin();
4162 return *ret0->begin();
4166 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4167 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4168 * 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
4169 * 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).
4170 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4172 * \a this is expected to be a mesh so that its space dimension is equal to its
4173 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4174 * 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).
4176 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4177 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4179 * \param [in] pts the list of points in which each tuple represents a point
4180 * \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.
4181 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4182 * \throw if number of components of \a pts is not equal to the space dimension.
4183 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4184 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4186 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
4189 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4190 pts->checkAllocated();
4191 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4192 if(meshDim!=spaceDim-1)
4193 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4194 if(meshDim!=2 && meshDim!=1)
4195 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4196 if(pts->getNumberOfComponents()!=spaceDim)
4198 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4199 throw INTERP_KERNEL::Exception(oss.str().c_str());
4201 checkFullyDefined();
4202 int nbCells=getNumberOfCells();
4204 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4205 int nbOfPts=pts->getNumberOfTuples();
4206 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4208 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4209 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4210 std::vector<double> bbox;
4211 getBoundingBoxForBBTree(bbox);
4216 BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
4217 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4219 double x=std::numeric_limits<double>::max();
4220 std::vector<int> elems;
4221 myTree.getMinDistanceOfMax(ptsPtr,x);
4222 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4223 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4229 BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
4230 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4232 double x=std::numeric_limits<double>::max();
4233 std::vector<int> elems;
4234 myTree.getMinDistanceOfMax(ptsPtr,x);
4235 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4236 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4241 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4243 cellIds=ret1.retn();
4248 * \param [in] pt the start pointer (included) of the coordinates of the point
4249 * \param [in] cellIdsBg the start pointer (included) of cellIds
4250 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4251 * \param [in] nc nodal connectivity
4252 * \param [in] ncI nodal connectivity index
4253 * \param [in,out] ret0 the min distance between \a this and the external input point
4254 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4255 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4257 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)
4260 ret0=std::numeric_limits<double>::max();
4261 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4263 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4265 case INTERP_KERNEL::NORM_TRI3:
4267 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4269 { ret0=tmp; cellId=*zeCell; }
4272 case INTERP_KERNEL::NORM_QUAD4:
4273 case INTERP_KERNEL::NORM_POLYGON:
4275 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4277 { ret0=tmp; cellId=*zeCell; }
4281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4287 * \param [in] pt the start pointer (included) of the coordinates of the point
4288 * \param [in] cellIdsBg the start pointer (included) of cellIds
4289 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4290 * \param [in] nc nodal connectivity
4291 * \param [in] ncI nodal connectivity index
4292 * \param [in,out] ret0 the min distance between \a this and the external input point
4293 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4294 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4296 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)
4299 ret0=std::numeric_limits<double>::max();
4300 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4302 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4304 case INTERP_KERNEL::NORM_SEG2:
4306 std::size_t uselessEntry=0;
4307 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4310 { ret0=tmp; cellId=*zeCell; }
4314 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4320 * Finds cells in contact with a ball (i.e. a point with precision).
4321 * \warning This method is suitable if the caller intends to evaluate only one
4322 * point, for more points getCellsContainingPoints() is recommended as it is
4324 * \param [in] pos - array of coordinates of the ball central point.
4325 * \param [in] eps - ball radius.
4326 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4327 * if there are no such cells.
4328 * \throw If the coordinates array is not set.
4329 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4331 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4333 std::vector<int> elts;
4334 getCellsContainingPoint(pos,eps,elts);
4337 return elts.front();
4341 * Finds cells in contact with a ball (i.e. a point with precision).
4342 * \warning This method is suitable if the caller intends to evaluate only one
4343 * point, for more points getCellsContainingPoints() is recommended as it is
4345 * \param [in] pos - array of coordinates of the ball central point.
4346 * \param [in] eps - ball radius.
4347 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
4348 * before inserting ids.
4349 * \throw If the coordinates array is not set.
4350 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4352 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4353 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4355 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4357 std::vector<int> eltsIndex;
4358 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4363 namespace ParaMEDMEM
4365 template<const int SPACEDIMM>
4369 static const int MY_SPACEDIM=SPACEDIMM;
4370 static const int MY_MESHDIM=8;
4371 typedef int MyConnType;
4372 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4374 // useless, but for windows compilation ...
4375 const double* getCoordinatesPtr() const { return 0; }
4376 const int* getConnectivityPtr() const { return 0; }
4377 const int* getConnectivityIndexPtr() const { return 0; }
4378 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4382 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4384 INTERP_KERNEL::Edge *ret=0;
4387 case INTERP_KERNEL::NORM_SEG2:
4389 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4392 case INTERP_KERNEL::NORM_SEG3:
4394 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4395 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4396 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4397 bool colinearity=inters.areColinears();
4398 delete e1; delete e2;
4400 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4402 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4403 mapp2[bg[2]].second=false;
4407 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4413 * 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'.
4414 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4415 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4417 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4420 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.
4421 const double *coo=mDesc->getCoords()->getConstPointer();
4422 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4423 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4425 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4426 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4427 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4429 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4430 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4432 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4433 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4435 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4436 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4438 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4440 if((*it2).second.second)
4441 mapp[(*it2).second.first]=(*it2).first;
4442 ((*it2).second.first)->decrRef();
4447 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4451 int locId=nodeId-offset2;
4452 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4456 int locId=nodeId-offset1;
4457 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4459 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4462 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4463 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4464 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4466 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4468 int eltId1=abs(*desc1)-1;
4469 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4471 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4472 if(it==mappRev.end())
4474 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4485 template<int SPACEDIM>
4486 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4487 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4489 std::vector<double> bbox;
4490 eltsIndex.resize(nbOfPoints+1);
4493 getBoundingBoxForBBTree(bbox);
4494 int nbOfCells=getNumberOfCells();
4495 const int *conn=_nodal_connec->getConstPointer();
4496 const int *connI=_nodal_connec_index->getConstPointer();
4497 double bb[2*SPACEDIM];
4498 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4499 for(int i=0;i<nbOfPoints;i++)
4501 eltsIndex[i+1]=eltsIndex[i];
4502 for(int j=0;j<SPACEDIM;j++)
4504 bb[2*j]=pos[SPACEDIM*i+j];
4505 bb[2*j+1]=pos[SPACEDIM*i+j];
4507 std::vector<int> candidates;
4508 myTree.getIntersectingElems(bb,candidates);
4509 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4511 int sz=connI[(*iter)+1]-connI[*iter]-1;
4512 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4513 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4514 coords,conn+connI[*iter]+1,sz,eps))
4517 elts.push_back(*iter);
4523 * Finds cells in contact with several balls (i.e. points with precision).
4524 * This method is an extension of getCellContainingPoint() and
4525 * getCellsContainingPoint() for the case of multiple points.
4526 * \param [in] pos - an array of coordinates of points in full interlace mode :
4527 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4528 * this->getSpaceDimension() * \a nbOfPoints
4529 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4530 * \param [in] eps - radius of balls (i.e. the precision).
4531 * \param [in,out] elts - vector returning ids of found cells.
4532 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4533 * dividing cell ids in \a elts into groups each referring to one
4534 * point. Its every element (except the last one) is an index pointing to the
4535 * first id of a group of cells. For example cells in contact with the *i*-th
4536 * point are described by following range of indices:
4537 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4538 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4539 * Number of cells in contact with the *i*-th point is
4540 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4541 * \throw If the coordinates array is not set.
4542 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4544 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4545 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4547 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4548 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4550 int spaceDim=getSpaceDimension();
4551 int mDim=getMeshDimension();
4556 const double *coords=_coords->getConstPointer();
4557 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4564 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4566 else if(spaceDim==2)
4570 const double *coords=_coords->getConstPointer();
4571 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4574 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4576 else if(spaceDim==1)
4580 const double *coords=_coords->getConstPointer();
4581 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4584 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4587 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4591 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4592 * least two its edges intersect each other anywhere except their extremities. An
4593 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4594 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4595 * cleared before filling in.
4596 * \param [in] eps - precision.
4597 * \throw If \a this->getMeshDimension() != 2.
4598 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4600 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4602 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4603 if(getMeshDimension()!=2)
4604 throw INTERP_KERNEL::Exception(msg);
4605 int spaceDim=getSpaceDimension();
4606 if(spaceDim!=2 && spaceDim!=3)
4607 throw INTERP_KERNEL::Exception(msg);
4608 const int *conn=_nodal_connec->getConstPointer();
4609 const int *connI=_nodal_connec_index->getConstPointer();
4610 int nbOfCells=getNumberOfCells();
4611 std::vector<double> cell2DinS2;
4612 for(int i=0;i<nbOfCells;i++)
4614 int offset=connI[i];
4615 int nbOfNodesForCell=connI[i+1]-offset-1;
4616 if(nbOfNodesForCell<=3)
4618 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4619 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4620 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4627 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4629 * 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.
4630 * 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.
4632 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4633 * This convex envelop is computed using Jarvis march algorithm.
4634 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4635 * 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)
4636 * 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.
4638 * \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.
4640 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4642 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4643 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4644 checkFullyDefined();
4645 const double *coords=getCoords()->getConstPointer();
4646 int nbOfCells=getNumberOfCells();
4647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4648 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4649 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4650 int *workIndexOut=nodalConnecIndexOut->getPointer();
4652 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4653 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4654 std::set<INTERP_KERNEL::NormalizedCellType> types;
4655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4656 isChanged->alloc(0,1);
4657 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4659 int pos=nodalConnecOut->getNumberOfTuples();
4660 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4661 isChanged->pushBackSilent(i);
4662 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4663 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4665 if(isChanged->empty())
4667 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4669 return isChanged.retn();
4673 * This method is \b NOT const because it can modify \a this.
4674 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4675 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4676 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4677 * \b 1 for translation and rotation around point of 'mesh1D'.
4678 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4680 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4682 checkFullyDefined();
4683 mesh1D->checkFullyDefined();
4684 if(!mesh1D->isContiguous1D())
4685 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4686 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4687 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4688 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4689 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4690 if(mesh1D->getMeshDimension()!=1)
4691 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4693 if(isPresenceOfQuadratic())
4695 if(mesh1D->isFullyQuadratic())
4698 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4701 int oldNbOfNodes=getNumberOfNodes();
4702 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4707 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4712 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4716 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4718 setCoords(newCoords);
4719 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4725 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4726 * If it is not the case an exception will be thrown.
4727 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4728 * intersection of plane defined by ('origin','vec').
4729 * This method has one in/out parameter : 'cut3DCurve'.
4730 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4731 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4732 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4733 * This method will throw an exception if \a this contains a non linear segment.
4735 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4737 checkFullyDefined();
4738 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4739 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4740 int ncells=getNumberOfCells();
4741 int nnodes=getNumberOfNodes();
4742 double vec2[3],vec3[3],vec4[3];
4743 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4746 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4747 const int *conn=_nodal_connec->getConstPointer();
4748 const int *connI=_nodal_connec_index->getConstPointer();
4749 const double *coo=_coords->getConstPointer();
4750 std::vector<double> addCoo;
4751 for(int i=0;i<ncells;i++)
4753 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4755 if(cut3DCurve[i]==-2)
4757 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4758 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];
4759 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4760 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4761 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4763 const double *st2=coo+3*st;
4764 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4765 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]));
4766 if(pos>eps && pos<1-eps)
4768 int nNode=((int)addCoo.size())/3;
4769 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4770 addCoo.insert(addCoo.end(),vec4,vec4+3);
4771 cut3DCurve[i]=nnodes+nNode;
4777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4781 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4782 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4783 coo2->alloc(newNbOfNodes,3);
4784 double *tmp=coo2->getPointer();
4785 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4786 std::copy(addCoo.begin(),addCoo.end(),tmp);
4787 DataArrayDouble::SetArrayIn(coo2,_coords);
4792 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4793 * \param mesh1D is the input 1D mesh used for translation computation.
4794 * \return newCoords new coords filled by this method.
4796 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4798 int oldNbOfNodes=getNumberOfNodes();
4799 int nbOf1DCells=mesh1D->getNumberOfCells();
4800 int spaceDim=getSpaceDimension();
4801 DataArrayDouble *ret=DataArrayDouble::New();
4802 std::vector<bool> isQuads;
4803 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4804 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4805 double *retPtr=ret->getPointer();
4806 const double *coords=getCoords()->getConstPointer();
4807 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4809 std::vector<double> c;
4813 for(int i=0;i<nbOf1DCells;i++)
4816 mesh1D->getNodeIdsOfCell(i,v);
4818 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4819 mesh1D->getCoordinatesOfNode(v[0],c);
4820 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4821 for(int j=0;j<oldNbOfNodes;j++)
4822 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4826 mesh1D->getCoordinatesOfNode(v[1],c);
4827 mesh1D->getCoordinatesOfNode(v[0],c);
4828 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4829 for(int j=0;j<oldNbOfNodes;j++)
4830 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4833 ret->copyStringInfoFrom(*getCoords());
4838 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4839 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4840 * \return newCoords new coords filled by this method.
4842 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4844 if(mesh1D->getSpaceDimension()==2)
4845 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4846 if(mesh1D->getSpaceDimension()==3)
4847 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4848 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4852 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4853 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4854 * \return newCoords new coords filled by this method.
4856 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4860 int oldNbOfNodes=getNumberOfNodes();
4861 int nbOf1DCells=mesh1D->getNumberOfCells();
4863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4864 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4865 int nbOfLevsInVec=nbOf1DCells+1;
4866 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4867 double *retPtr=ret->getPointer();
4868 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4869 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4870 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4871 tmp->setCoords(tmp2);
4872 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4873 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4874 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4875 for(int i=1;i<nbOfLevsInVec;i++)
4877 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4878 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4879 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4880 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4881 tmp->translate(vec);
4882 double tmp3[2],radius,alpha,alpha0;
4883 const double *p0=i+1<nbOfLevsInVec?begin:third;
4884 const double *p1=i+1<nbOfLevsInVec?end:begin;
4885 const double *p2=i+1<nbOfLevsInVec?third:end;
4886 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4887 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]);
4888 double angle=acos(cosangle/(radius*radius));
4889 tmp->rotate(end,0,angle);
4890 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4896 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4897 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4898 * \return newCoords new coords filled by this method.
4900 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4904 int oldNbOfNodes=getNumberOfNodes();
4905 int nbOf1DCells=mesh1D->getNumberOfCells();
4907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4908 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4909 int nbOfLevsInVec=nbOf1DCells+1;
4910 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4911 double *retPtr=ret->getPointer();
4912 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4913 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4914 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4915 tmp->setCoords(tmp2);
4916 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4917 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4918 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4919 for(int i=1;i<nbOfLevsInVec;i++)
4921 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4922 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4923 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4924 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4925 tmp->translate(vec);
4926 double tmp3[2],radius,alpha,alpha0;
4927 const double *p0=i+1<nbOfLevsInVec?begin:third;
4928 const double *p1=i+1<nbOfLevsInVec?end:begin;
4929 const double *p2=i+1<nbOfLevsInVec?third:end;
4930 double vecPlane[3]={
4931 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4932 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4933 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4935 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4938 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4939 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4940 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4942 double c2=cos(asin(s2));
4944 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4945 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4946 {-vec2[1]*s2, vec2[0]*s2, c2}
4948 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]};
4949 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]};
4950 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]};
4951 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4952 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]);
4953 double angle=acos(cosangle/(radius*radius));
4954 tmp->rotate(end,vecPlane,angle);
4957 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4963 * This method is private because not easy to use for end user. This method is const contrary to
4964 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4965 * the coords sorted slice by slice.
4966 * \param isQuad specifies presence of quadratic cells.
4968 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4970 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4971 int nbOf2DCells=getNumberOfCells();
4972 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4973 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4974 const int *conn=_nodal_connec->getConstPointer();
4975 const int *connI=_nodal_connec_index->getConstPointer();
4976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4978 newConnI->alloc(nbOf3DCells+1,1);
4979 int *newConnIPtr=newConnI->getPointer();
4981 std::vector<int> newc;
4982 for(int j=0;j<nbOf2DCells;j++)
4984 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4985 *newConnIPtr++=(int)newc.size();
4987 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4988 int *newConnPtr=newConn->getPointer();
4989 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4990 newConnIPtr=newConnI->getPointer();
4991 for(int iz=0;iz<nbOf1DCells;iz++)
4994 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4995 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4997 int icell=(int)(iter-newc.begin());
4998 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
5001 *newConnPtr=(*iter)+iz*deltaPerLev;
5006 *newConnPtr=(*iter);
5009 ret->setConnectivity(newConn,newConnI,true);
5010 ret->setCoords(getCoords());
5015 * Checks if \a this mesh is constituted by only quadratic cells.
5016 * \return bool - \c true if there are only quadratic cells in \a this mesh.
5017 * \throw If the coordinates array is not set.
5018 * \throw If the nodal connectivity of cells is not defined.
5020 bool MEDCouplingUMesh::isFullyQuadratic() const
5022 checkFullyDefined();
5024 int nbOfCells=getNumberOfCells();
5025 for(int i=0;i<nbOfCells && ret;i++)
5027 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5028 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5029 ret=cm.isQuadratic();
5035 * Checks if \a this mesh includes any quadratic cell.
5036 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5037 * \throw If the coordinates array is not set.
5038 * \throw If the nodal connectivity of cells is not defined.
5040 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5042 checkFullyDefined();
5044 int nbOfCells=getNumberOfCells();
5045 for(int i=0;i<nbOfCells && !ret;i++)
5047 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5048 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5049 ret=cm.isQuadratic();
5055 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5056 * this mesh, it remains unchanged.
5057 * \throw If the coordinates array is not set.
5058 * \throw If the nodal connectivity of cells is not defined.
5060 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
5062 checkFullyDefined();
5063 int nbOfCells=getNumberOfCells();
5065 const int *iciptr=_nodal_connec_index->getConstPointer();
5066 for(int i=0;i<nbOfCells;i++)
5068 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5069 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5070 if(cm.isQuadratic())
5072 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5073 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5074 if(!cml.isDynamic())
5075 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5077 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5082 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5084 const int *icptr=_nodal_connec->getConstPointer();
5085 newConn->alloc(getMeshLength()-delta,1);
5086 newConnI->alloc(nbOfCells+1,1);
5087 int *ocptr=newConn->getPointer();
5088 int *ociptr=newConnI->getPointer();
5091 for(int i=0;i<nbOfCells;i++,ociptr++)
5093 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5094 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5095 if(!cm.isQuadratic())
5097 _types.insert(type);
5098 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5099 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5103 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5104 _types.insert(typel);
5105 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5106 int newNbOfNodes=cml.getNumberOfNodes();
5108 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5109 *ocptr++=(int)typel;
5110 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5111 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5114 setConnectivity(newConn,newConnI,false);
5118 * This method converts all linear cell in \a this to quadratic one.
5119 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5120 * 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)
5121 * 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.
5122 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5123 * end of the existing coordinates.
5125 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5126 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5127 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5129 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5131 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5133 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
5135 DataArrayInt *conn=0,*connI=0;
5136 DataArrayDouble *coords=0;
5137 std::set<INTERP_KERNEL::NormalizedCellType> types;
5138 checkFullyDefined();
5139 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5140 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5141 int meshDim=getMeshDimension();
5142 switch(conversionType)
5148 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5149 connSafe=conn; connISafe=connI; coordsSafe=coords;
5152 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5153 connSafe=conn; connISafe=connI; coordsSafe=coords;
5156 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5157 connSafe=conn; connISafe=connI; coordsSafe=coords;
5160 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5168 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5169 connSafe=conn; connISafe=connI; coordsSafe=coords;
5172 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5173 connSafe=conn; connISafe=connI; coordsSafe=coords;
5176 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5177 connSafe=conn; connISafe=connI; coordsSafe=coords;
5180 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5185 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5187 setConnectivity(connSafe,connISafe,false);
5189 setCoords(coordsSafe);
5194 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5195 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5196 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5198 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5200 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5202 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5203 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5204 int nbOfCells=getNumberOfCells();
5205 int nbOfNodes=getNumberOfNodes();
5206 const int *cPtr=_nodal_connec->getConstPointer();
5207 const int *icPtr=_nodal_connec_index->getConstPointer();
5208 int lastVal=0,offset=nbOfNodes;
5209 for(int i=0;i<nbOfCells;i++,icPtr++)
5211 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5212 if(type==INTERP_KERNEL::NORM_SEG2)
5214 types.insert(INTERP_KERNEL::NORM_SEG3);
5215 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5216 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5217 newConn->pushBackSilent(offset++);
5219 newConnI->pushBackSilent(lastVal);
5220 ret->pushBackSilent(i);
5225 lastVal+=(icPtr[1]-icPtr[0]);
5226 newConnI->pushBackSilent(lastVal);
5227 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5230 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5231 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5235 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)
5237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5241 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5242 DataArrayInt *conn1D=0,*conn1DI=0;
5243 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5244 DataArrayDouble *coordsTmp=0;
5245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5246 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5248 const int *c1DPtr=conn1D->begin();
5249 const int *c1DIPtr=conn1DI->begin();
5250 int nbOfCells=getNumberOfCells();
5251 const int *cPtr=_nodal_connec->getConstPointer();
5252 const int *icPtr=_nodal_connec_index->getConstPointer();
5254 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5256 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5257 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5258 if(!cm.isQuadratic())
5260 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5261 types.insert(typ2); newConn->pushBackSilent(typ2);
5262 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5263 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5264 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5265 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5266 newConnI->pushBackSilent(lastVal);
5267 ret->pushBackSilent(i);
5272 lastVal+=(icPtr[1]-icPtr[0]);
5273 newConnI->pushBackSilent(lastVal);
5274 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5277 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5282 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5283 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5284 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5286 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5290 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5291 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5294 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5297 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5303 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5304 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5305 DataArrayInt *conn1D=0,*conn1DI=0;
5306 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5307 DataArrayDouble *coordsTmp=0;
5308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5309 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5311 const int *c1DPtr=conn1D->begin();
5312 const int *c1DIPtr=conn1DI->begin();
5313 int nbOfCells=getNumberOfCells();
5314 const int *cPtr=_nodal_connec->getConstPointer();
5315 const int *icPtr=_nodal_connec_index->getConstPointer();
5316 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5317 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5319 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5320 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5321 if(!cm.isQuadratic())
5323 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5324 types.insert(typ2); newConn->pushBackSilent(typ2);
5325 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5326 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5327 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5328 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5329 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5330 newConnI->pushBackSilent(lastVal);
5331 ret->pushBackSilent(i);
5336 lastVal+=(icPtr[1]-icPtr[0]);
5337 newConnI->pushBackSilent(lastVal);
5338 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5341 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5342 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5347 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5348 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5349 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5351 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5354 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5355 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5358 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5361 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5363 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5367 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5369 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5370 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5371 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5372 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5373 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5376 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5378 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5380 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5381 int nbOfCells=getNumberOfCells();
5382 const int *cPtr=_nodal_connec->getConstPointer();
5383 const int *icPtr=_nodal_connec_index->getConstPointer();
5384 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5385 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5387 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5388 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5389 if(!cm.isQuadratic())
5391 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5392 if(typ2==INTERP_KERNEL::NORM_ERROR)
5394 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5395 throw INTERP_KERNEL::Exception(oss.str().c_str());
5397 types.insert(typ2); newConn->pushBackSilent(typ2);
5398 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5399 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5400 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5401 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5403 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5404 int tmpPos=newConn->getNumberOfTuples();
5405 newConn->pushBackSilent(nodeId2);
5406 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5408 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5409 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5410 newConnI->pushBackSilent(lastVal);
5411 ret->pushBackSilent(i);
5416 lastVal+=(icPtr[1]-icPtr[0]);
5417 newConnI->pushBackSilent(lastVal);
5418 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5422 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5423 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5424 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5425 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5426 int *c=newConn->getPointer();
5427 const int *cI(newConnI->begin());
5428 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5429 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5430 offset=coordsTmp2Safe->getNumberOfTuples();
5431 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5432 c[cI[(*elt)+1]-1]+=offset;
5433 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5438 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5439 * so that the number of cells remains the same. Quadratic faces are converted to
5440 * polygons. This method works only for 2D meshes in
5441 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5442 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5443 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5444 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5445 * a polylinized edge constituting the input polygon.
5446 * \throw If the coordinates array is not set.
5447 * \throw If the nodal connectivity of cells is not defined.
5448 * \throw If \a this->getMeshDimension() != 2.
5449 * \throw If \a this->getSpaceDimension() != 2.
5451 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5453 checkFullyDefined();
5454 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5455 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5456 double epsa=fabs(eps);
5457 if(epsa<std::numeric_limits<double>::min())
5458 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 !");
5459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5463 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5464 revDesc1=0; revDescIndx1=0;
5465 mDesc->tessellate2DCurve(eps);
5466 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5467 setCoords(mDesc->getCoords());
5471 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5472 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5473 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5474 * a sub-divided edge.
5475 * \throw If the coordinates array is not set.
5476 * \throw If the nodal connectivity of cells is not defined.
5477 * \throw If \a this->getMeshDimension() != 1.
5478 * \throw If \a this->getSpaceDimension() != 2.
5480 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5482 checkFullyDefined();
5483 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5484 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5485 double epsa=fabs(eps);
5486 if(epsa<std::numeric_limits<double>::min())
5487 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 !");
5488 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5489 int nbCells=getNumberOfCells();
5490 int nbNodes=getNumberOfNodes();
5491 const int *conn=_nodal_connec->getConstPointer();
5492 const int *connI=_nodal_connec_index->getConstPointer();
5493 const double *coords=_coords->getConstPointer();
5494 std::vector<double> addCoo;
5495 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5496 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5497 newConnI->alloc(nbCells+1,1);
5498 int *newConnIPtr=newConnI->getPointer();
5501 INTERP_KERNEL::Node *tmp2[3];
5502 std::set<INTERP_KERNEL::NormalizedCellType> types;
5503 for(int i=0;i<nbCells;i++,newConnIPtr++)
5505 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5506 if(cm.isQuadratic())
5507 {//assert(connI[i+1]-connI[i]-1==3)
5508 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5509 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5510 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5511 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5512 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5515 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5516 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5518 newConnIPtr[1]=(int)newConn.size();
5522 types.insert(INTERP_KERNEL::NORM_SEG2);
5523 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5524 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5525 newConnIPtr[1]=newConnIPtr[0]+3;
5530 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5531 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5532 newConnIPtr[1]=newConnIPtr[0]+3;
5535 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5538 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5540 newConnArr->alloc((int)newConn.size(),1);
5541 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5542 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5543 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5544 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5545 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5546 std::copy(addCoo.begin(),addCoo.end(),work);
5547 DataArrayDouble::SetArrayIn(newCoords,_coords);
5552 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5553 * In addition, returns an array mapping new cells to old ones. <br>
5554 * This method typically increases the number of cells in \a this mesh
5555 * but the number of nodes remains \b unchanged.
5556 * That's why the 3D splitting policies
5557 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5558 * \param [in] policy - specifies a pattern used for splitting.
5559 * The semantic of \a policy is:
5560 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5561 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5562 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5563 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5564 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5565 * an id of old cell producing it. The caller is to delete this array using
5566 * decrRef() as it is no more needed.
5567 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5568 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5569 * and \a this->getMeshDimension() != 3.
5570 * \throw If \a policy is not one of the four discussed above.
5571 * \throw If the nodal connectivity of cells is not defined.
5573 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5578 return simplexizePol0();
5580 return simplexizePol1();
5581 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5582 return simplexizePlanarFace5();
5583 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5584 return simplexizePlanarFace6();
5586 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)");
5591 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5592 * - 1D: INTERP_KERNEL::NORM_SEG2
5593 * - 2D: INTERP_KERNEL::NORM_TRI3
5594 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5596 * This method is useful for users that need to use P1 field services as
5597 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5598 * All these methods need mesh support containing only simplex cells.
5599 * \return bool - \c true if there are only simplex cells in \a this mesh.
5600 * \throw If the coordinates array is not set.
5601 * \throw If the nodal connectivity of cells is not defined.
5602 * \throw If \a this->getMeshDimension() < 1.
5604 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5606 checkFullyDefined();
5607 int mdim=getMeshDimension();
5608 if(mdim<1 || mdim>3)
5609 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5610 int nbCells=getNumberOfCells();
5611 const int *conn=_nodal_connec->getConstPointer();
5612 const int *connI=_nodal_connec_index->getConstPointer();
5613 for(int i=0;i<nbCells;i++)
5615 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5623 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5625 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5627 checkConnectivityFullyDefined();
5628 if(getMeshDimension()!=2)
5629 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5630 int nbOfCells=getNumberOfCells();
5631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5632 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5633 ret->alloc(nbOfCells+nbOfCutCells,1);
5634 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5635 int *retPt=ret->getPointer();
5636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5638 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5639 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5640 int *pt=newConn->getPointer();
5641 int *ptI=newConnI->getPointer();
5643 const int *oldc=_nodal_connec->getConstPointer();
5644 const int *ci=_nodal_connec_index->getConstPointer();
5645 for(int i=0;i<nbOfCells;i++,ci++)
5647 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5649 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5650 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5651 pt=std::copy(tmp,tmp+8,pt);
5660 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5661 ptI[1]=ptI[0]+ci[1]-ci[0];
5666 _nodal_connec->decrRef();
5667 _nodal_connec=newConn.retn();
5668 _nodal_connec_index->decrRef();
5669 _nodal_connec_index=newConnI.retn();
5676 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5678 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5680 checkConnectivityFullyDefined();
5681 if(getMeshDimension()!=2)
5682 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5683 int nbOfCells=getNumberOfCells();
5684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5685 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5686 ret->alloc(nbOfCells+nbOfCutCells,1);
5687 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5688 int *retPt=ret->getPointer();
5689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5691 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5692 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5693 int *pt=newConn->getPointer();
5694 int *ptI=newConnI->getPointer();
5696 const int *oldc=_nodal_connec->getConstPointer();
5697 const int *ci=_nodal_connec_index->getConstPointer();
5698 for(int i=0;i<nbOfCells;i++,ci++)
5700 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5702 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5703 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5704 pt=std::copy(tmp,tmp+8,pt);
5713 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5714 ptI[1]=ptI[0]+ci[1]-ci[0];
5719 _nodal_connec->decrRef();
5720 _nodal_connec=newConn.retn();
5721 _nodal_connec_index->decrRef();
5722 _nodal_connec_index=newConnI.retn();
5729 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5731 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5733 checkConnectivityFullyDefined();
5734 if(getMeshDimension()!=3)
5735 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5736 int nbOfCells=getNumberOfCells();
5737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5738 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5739 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5740 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5741 int *retPt=ret->getPointer();
5742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5744 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5745 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5746 int *pt=newConn->getPointer();
5747 int *ptI=newConnI->getPointer();
5749 const int *oldc=_nodal_connec->getConstPointer();
5750 const int *ci=_nodal_connec_index->getConstPointer();
5751 for(int i=0;i<nbOfCells;i++,ci++)
5753 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5755 for(int j=0;j<5;j++,pt+=5,ptI++)
5757 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5758 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];
5765 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5766 ptI[1]=ptI[0]+ci[1]-ci[0];
5771 _nodal_connec->decrRef();
5772 _nodal_connec=newConn.retn();
5773 _nodal_connec_index->decrRef();
5774 _nodal_connec_index=newConnI.retn();
5781 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5783 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5785 checkConnectivityFullyDefined();
5786 if(getMeshDimension()!=3)
5787 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5788 int nbOfCells=getNumberOfCells();
5789 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5790 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5791 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5792 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5793 int *retPt=ret->getPointer();
5794 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5795 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5796 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5797 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5798 int *pt=newConn->getPointer();
5799 int *ptI=newConnI->getPointer();
5801 const int *oldc=_nodal_connec->getConstPointer();
5802 const int *ci=_nodal_connec_index->getConstPointer();
5803 for(int i=0;i<nbOfCells;i++,ci++)
5805 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5807 for(int j=0;j<6;j++,pt+=5,ptI++)
5809 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5810 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];
5817 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5818 ptI[1]=ptI[0]+ci[1]-ci[0];
5823 _nodal_connec->decrRef();
5824 _nodal_connec=newConn.retn();
5825 _nodal_connec_index->decrRef();
5826 _nodal_connec_index=newConnI.retn();
5833 * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5834 * This method completly ignore coordinates.
5835 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5836 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5837 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5838 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5840 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5842 checkFullyDefined();
5843 if(getMeshDimension()!=2)
5844 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5845 int nbOfCells=getNumberOfCells();
5846 int *connI=_nodal_connec_index->getPointer();
5848 for(int i=0;i<nbOfCells;i++,connI++)
5850 int offset=descIndex[i];
5851 int nbOfEdges=descIndex[i+1]-offset;
5853 bool ddirect=desc[offset+nbOfEdges-1]>0;
5854 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5855 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5856 for(int j=0;j<nbOfEdges;j++)
5858 bool direct=desc[offset+j]>0;
5859 int edgeId=std::abs(desc[offset+j])-1;
5860 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5862 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5863 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5864 int ref2=direct?id1:id2;
5867 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5868 newConnLgth+=nbOfSubNodes-1;
5873 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5874 throw INTERP_KERNEL::Exception(oss.str().c_str());
5879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5882 newConnLgth++;//+1 is for cell type
5883 connI[1]=newConnLgth;
5886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5887 newConn->alloc(newConnLgth,1);
5888 int *work=newConn->getPointer();
5889 for(int i=0;i<nbOfCells;i++)
5891 *work++=INTERP_KERNEL::NORM_POLYGON;
5892 int offset=descIndex[i];
5893 int nbOfEdges=descIndex[i+1]-offset;
5894 for(int j=0;j<nbOfEdges;j++)
5896 bool direct=desc[offset+j]>0;
5897 int edgeId=std::abs(desc[offset+j])-1;
5899 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5902 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5903 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5904 work=std::copy(it,it+nbOfSubNodes-1,work);
5908 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5911 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5915 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5916 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5917 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5918 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5919 * so it can be useful to call mergeNodes() before calling this method.
5920 * \throw If \a this->getMeshDimension() <= 1.
5921 * \throw If the coordinates array is not set.
5922 * \throw If the nodal connectivity of cells is not defined.
5924 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5926 checkFullyDefined();
5927 if(getMeshDimension()<=1)
5928 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5929 int nbOfCells=getNumberOfCells();
5932 int initMeshLgth=getMeshLength();
5933 int *conn=_nodal_connec->getPointer();
5934 int *index=_nodal_connec_index->getPointer();
5938 for(int i=0;i<nbOfCells;i++)
5940 lgthOfCurCell=index[i+1]-posOfCurCell;
5941 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5943 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5944 conn+newPos+1,newLgth);
5945 conn[newPos]=newType;
5947 posOfCurCell=index[i+1];
5950 if(newPos!=initMeshLgth)
5951 _nodal_connec->reAlloc(newPos);
5956 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5957 * A cell is considered to be oriented correctly if an angle between its
5958 * normal vector and a given vector is less than \c PI / \c 2.
5959 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5961 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5963 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5964 * is not cleared before filling in.
5965 * \throw If \a this->getMeshDimension() != 2.
5966 * \throw If \a this->getSpaceDimension() != 3.
5968 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5969 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5971 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5973 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5974 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5975 int nbOfCells=getNumberOfCells();
5976 const int *conn=_nodal_connec->getConstPointer();
5977 const int *connI=_nodal_connec_index->getConstPointer();
5978 const double *coordsPtr=_coords->getConstPointer();
5979 for(int i=0;i<nbOfCells;i++)
5981 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5982 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5984 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5985 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5992 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5993 * considered to be oriented correctly if an angle between its normal vector and a
5994 * given vector is less than \c PI / \c 2.
5995 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5997 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5999 * \throw If \a this->getMeshDimension() != 2.
6000 * \throw If \a this->getSpaceDimension() != 3.
6002 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6003 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6005 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
6007 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6008 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6009 int nbOfCells=getNumberOfCells();
6010 int *conn=_nodal_connec->getPointer();
6011 const int *connI=_nodal_connec_index->getConstPointer();
6012 const double *coordsPtr=_coords->getConstPointer();
6013 bool isModified=false;
6014 for(int i=0;i<nbOfCells;i++)
6016 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6017 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6019 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6020 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6023 std::vector<int> tmp(connI[i+1]-connI[i]-2);
6024 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
6025 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
6030 _nodal_connec->declareAsNew();
6035 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6036 * oriented facets. The normal vector of the facet should point out of the cell.
6037 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6038 * is not cleared before filling in.
6039 * \throw If \a this->getMeshDimension() != 3.
6040 * \throw If \a this->getSpaceDimension() != 3.
6041 * \throw If the coordinates array is not set.
6042 * \throw If the nodal connectivity of cells is not defined.
6044 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6045 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6047 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
6049 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6050 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6051 int nbOfCells=getNumberOfCells();
6052 const int *conn=_nodal_connec->getConstPointer();
6053 const int *connI=_nodal_connec_index->getConstPointer();
6054 const double *coordsPtr=_coords->getConstPointer();
6055 for(int i=0;i<nbOfCells;i++)
6057 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6058 if(type==INTERP_KERNEL::NORM_POLYHED)
6060 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6067 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6069 * \throw If \a this->getMeshDimension() != 3.
6070 * \throw If \a this->getSpaceDimension() != 3.
6071 * \throw If the coordinates array is not set.
6072 * \throw If the nodal connectivity of cells is not defined.
6073 * \throw If the reparation fails.
6075 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6076 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6077 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6079 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
6081 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6082 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6083 int nbOfCells=getNumberOfCells();
6084 int *conn=_nodal_connec->getPointer();
6085 const int *connI=_nodal_connec_index->getConstPointer();
6086 const double *coordsPtr=_coords->getConstPointer();
6087 for(int i=0;i<nbOfCells;i++)
6089 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6090 if(type==INTERP_KERNEL::NORM_POLYHED)
6094 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6095 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6097 catch(INTERP_KERNEL::Exception& e)
6099 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6100 throw INTERP_KERNEL::Exception(oss.str().c_str());
6108 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6109 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6110 * according to which the first facet of the cell should be oriented to have the normal vector
6111 * pointing out of cell.
6112 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6113 * cells. The caller is to delete this array using decrRef() as it is no more
6115 * \throw If \a this->getMeshDimension() != 3.
6116 * \throw If \a this->getSpaceDimension() != 3.
6117 * \throw If the coordinates array is not set.
6118 * \throw If the nodal connectivity of cells is not defined.
6120 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6121 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6122 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6124 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
6126 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6127 if(getMeshDimension()!=3)
6128 throw INTERP_KERNEL::Exception(msg);
6129 int spaceDim=getSpaceDimension();
6131 throw INTERP_KERNEL::Exception(msg);
6133 int nbOfCells=getNumberOfCells();
6134 int *conn=_nodal_connec->getPointer();
6135 const int *connI=_nodal_connec_index->getConstPointer();
6136 const double *coo=getCoords()->getConstPointer();
6137 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6138 for(int i=0;i<nbOfCells;i++)
6140 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6141 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6143 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6145 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6146 cells->pushBackSilent(i);
6150 return cells.retn();
6154 * This method is a faster method to correct orientation of all 3D cells in \a this.
6155 * 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.
6156 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6158 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6159 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6161 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
6163 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6164 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6165 int nbOfCells=getNumberOfCells();
6166 int *conn=_nodal_connec->getPointer();
6167 const int *connI=_nodal_connec_index->getConstPointer();
6168 const double *coordsPtr=_coords->getConstPointer();
6169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6170 for(int i=0;i<nbOfCells;i++)
6172 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6175 case INTERP_KERNEL::NORM_TETRA4:
6177 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6179 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6180 ret->pushBackSilent(i);
6184 case INTERP_KERNEL::NORM_PYRA5:
6186 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6188 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6189 ret->pushBackSilent(i);
6193 case INTERP_KERNEL::NORM_PENTA6:
6194 case INTERP_KERNEL::NORM_HEXA8:
6195 case INTERP_KERNEL::NORM_HEXGP12:
6197 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6199 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6200 ret->pushBackSilent(i);
6204 case INTERP_KERNEL::NORM_POLYHED:
6206 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6208 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6209 ret->pushBackSilent(i);
6214 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 !");
6222 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6223 * If it is not the case an exception will be thrown.
6224 * This method is fast because the first cell of \a this is used to compute the plane.
6225 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6226 * \param pos output of size at least 3 used to store a point owned of searched plane.
6228 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
6230 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6231 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6232 const int *conn=_nodal_connec->getConstPointer();
6233 const int *connI=_nodal_connec_index->getConstPointer();
6234 const double *coordsPtr=_coords->getConstPointer();
6235 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6236 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6240 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6241 * cells. Currently cells of the following types are treated:
6242 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6243 * For a cell of other type an exception is thrown.
6244 * Space dimension of a 2D mesh can be either 2 or 3.
6245 * The Edge Ratio of a cell \f$t\f$ is:
6246 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6247 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6248 * the smallest edge lengths of \f$t\f$.
6249 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6250 * cells and one time, lying on \a this mesh. The caller is to delete this
6251 * field using decrRef() as it is no more needed.
6252 * \throw If the coordinates array is not set.
6253 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6254 * \throw If the connectivity data array has more than one component.
6255 * \throw If the connectivity data array has a named component.
6256 * \throw If the connectivity index data array has more than one component.
6257 * \throw If the connectivity index data array has a named component.
6258 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6259 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6260 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6262 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
6265 int spaceDim=getSpaceDimension();
6266 int meshDim=getMeshDimension();
6267 if(spaceDim!=2 && spaceDim!=3)
6268 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6269 if(meshDim!=2 && meshDim!=3)
6270 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6271 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6273 int nbOfCells=getNumberOfCells();
6274 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6275 arr->alloc(nbOfCells,1);
6276 double *pt=arr->getPointer();
6277 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6278 const int *conn=_nodal_connec->getConstPointer();
6279 const int *connI=_nodal_connec_index->getConstPointer();
6280 const double *coo=_coords->getConstPointer();
6282 for(int i=0;i<nbOfCells;i++,pt++)
6284 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6287 case INTERP_KERNEL::NORM_TRI3:
6289 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6290 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6293 case INTERP_KERNEL::NORM_QUAD4:
6295 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6296 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6299 case INTERP_KERNEL::NORM_TETRA4:
6301 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6302 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6306 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6308 conn+=connI[i+1]-connI[i];
6310 ret->setName("EdgeRatio");
6311 ret->synchronizeTimeWithSupport();
6316 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6317 * cells. Currently cells of the following types are treated:
6318 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6319 * For a cell of other type an exception is thrown.
6320 * Space dimension of a 2D mesh can be either 2 or 3.
6321 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6322 * cells and one time, lying on \a this mesh. The caller is to delete this
6323 * field using decrRef() as it is no more needed.
6324 * \throw If the coordinates array is not set.
6325 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6326 * \throw If the connectivity data array has more than one component.
6327 * \throw If the connectivity data array has a named component.
6328 * \throw If the connectivity index data array has more than one component.
6329 * \throw If the connectivity index data array has a named component.
6330 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6331 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6332 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6334 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6337 int spaceDim=getSpaceDimension();
6338 int meshDim=getMeshDimension();
6339 if(spaceDim!=2 && spaceDim!=3)
6340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6341 if(meshDim!=2 && meshDim!=3)
6342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6343 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6345 int nbOfCells=getNumberOfCells();
6346 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6347 arr->alloc(nbOfCells,1);
6348 double *pt=arr->getPointer();
6349 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6350 const int *conn=_nodal_connec->getConstPointer();
6351 const int *connI=_nodal_connec_index->getConstPointer();
6352 const double *coo=_coords->getConstPointer();
6354 for(int i=0;i<nbOfCells;i++,pt++)
6356 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6359 case INTERP_KERNEL::NORM_TRI3:
6361 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6362 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6365 case INTERP_KERNEL::NORM_QUAD4:
6367 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6368 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6371 case INTERP_KERNEL::NORM_TETRA4:
6373 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6374 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6378 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6380 conn+=connI[i+1]-connI[i];
6382 ret->setName("AspectRatio");
6383 ret->synchronizeTimeWithSupport();
6388 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6389 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6390 * treated: INTERP_KERNEL::NORM_QUAD4.
6391 * For a cell of other type an exception is thrown.
6392 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6393 * cells and one time, lying on \a this mesh. The caller is to delete this
6394 * field using decrRef() as it is no more needed.
6395 * \throw If the coordinates array is not set.
6396 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6397 * \throw If the connectivity data array has more than one component.
6398 * \throw If the connectivity data array has a named component.
6399 * \throw If the connectivity index data array has more than one component.
6400 * \throw If the connectivity index data array has a named component.
6401 * \throw If \a this->getMeshDimension() != 2.
6402 * \throw If \a this->getSpaceDimension() != 3.
6403 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6405 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6408 int spaceDim=getSpaceDimension();
6409 int meshDim=getMeshDimension();
6411 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6413 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6414 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6416 int nbOfCells=getNumberOfCells();
6417 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6418 arr->alloc(nbOfCells,1);
6419 double *pt=arr->getPointer();
6420 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6421 const int *conn=_nodal_connec->getConstPointer();
6422 const int *connI=_nodal_connec_index->getConstPointer();
6423 const double *coo=_coords->getConstPointer();
6425 for(int i=0;i<nbOfCells;i++,pt++)
6427 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6430 case INTERP_KERNEL::NORM_QUAD4:
6432 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6433 *pt=INTERP_KERNEL::quadWarp(tmp);
6437 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6439 conn+=connI[i+1]-connI[i];
6441 ret->setName("Warp");
6442 ret->synchronizeTimeWithSupport();
6448 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6449 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6450 * treated: INTERP_KERNEL::NORM_QUAD4.
6451 * For a cell of other type an exception is thrown.
6452 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6453 * cells and one time, lying on \a this mesh. The caller is to delete this
6454 * field using decrRef() as it is no more needed.
6455 * \throw If the coordinates array is not set.
6456 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6457 * \throw If the connectivity data array has more than one component.
6458 * \throw If the connectivity data array has a named component.
6459 * \throw If the connectivity index data array has more than one component.
6460 * \throw If the connectivity index data array has a named component.
6461 * \throw If \a this->getMeshDimension() != 2.
6462 * \throw If \a this->getSpaceDimension() != 3.
6463 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6465 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6468 int spaceDim=getSpaceDimension();
6469 int meshDim=getMeshDimension();
6471 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6473 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6474 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6476 int nbOfCells=getNumberOfCells();
6477 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6478 arr->alloc(nbOfCells,1);
6479 double *pt=arr->getPointer();
6480 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6481 const int *conn=_nodal_connec->getConstPointer();
6482 const int *connI=_nodal_connec_index->getConstPointer();
6483 const double *coo=_coords->getConstPointer();
6485 for(int i=0;i<nbOfCells;i++,pt++)
6487 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6490 case INTERP_KERNEL::NORM_QUAD4:
6492 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6493 *pt=INTERP_KERNEL::quadSkew(tmp);
6497 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6499 conn+=connI[i+1]-connI[i];
6501 ret->setName("Skew");
6502 ret->synchronizeTimeWithSupport();
6507 * This method aggregate the bbox of each cell and put it into bbox parameter.
6508 * \param bbox out parameter of size 2*spacedim*nbOfcells.
6510 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6512 int spaceDim=getSpaceDimension();
6513 int nbOfCells=getNumberOfCells();
6514 bbox.resize(2*nbOfCells*spaceDim);
6515 for(int i=0;i<nbOfCells*spaceDim;i++)
6517 bbox[2*i]=std::numeric_limits<double>::max();
6518 bbox[2*i+1]=-std::numeric_limits<double>::max();
6520 const double *coordsPtr=_coords->getConstPointer();
6521 const int *conn=_nodal_connec->getConstPointer();
6522 const int *connI=_nodal_connec_index->getConstPointer();
6523 for(int i=0;i<nbOfCells;i++)
6525 int offset=connI[i]+1;
6526 int nbOfNodesForCell=connI[i+1]-offset;
6527 for(int j=0;j<nbOfNodesForCell;j++)
6529 int nodeId=conn[offset+j];
6531 for(int k=0;k<spaceDim;k++)
6533 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6534 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6542 namespace ParaMEDMEMImpl
6547 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6548 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6557 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6558 bool operator() (const int& pos) { return _conn[pos]==_val; }
6568 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6569 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6570 * \a this is composed in cell types.
6571 * The returned array is of size 3*n where n is the number of different types present in \a this.
6572 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
6573 * This parameter is kept only for compatibility with other methode listed above.
6575 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6577 checkConnectivityFullyDefined();
6578 const int *conn=_nodal_connec->getConstPointer();
6579 const int *connI=_nodal_connec_index->getConstPointer();
6580 const int *work=connI;
6581 int nbOfCells=getNumberOfCells();
6582 std::size_t n=getAllTypes().size();
6583 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6584 std::set<INTERP_KERNEL::NormalizedCellType> types;
6585 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6587 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6588 if(types.find(typ)!=types.end())
6590 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6591 oss << " is not contiguous !";
6592 throw INTERP_KERNEL::Exception(oss.str().c_str());
6596 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6597 ret[3*i+1]=(int)std::distance(work,work2);
6604 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6605 * only for types cell, type node is not managed.
6606 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6607 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6608 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6609 * If 2 or more same geometric type is in \a code and exception is thrown too.
6611 * This method firstly checks
6612 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6613 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6614 * an exception is thrown too.
6616 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6617 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6618 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6620 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6624 std::size_t sz=code.size();
6627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6628 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6630 for(std::size_t i=0;i<n;i++)
6631 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6633 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6635 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6636 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6639 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6640 if(idsPerType.empty())
6642 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6643 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6644 if(types.size()==_types.size())
6647 DataArrayInt *ret=DataArrayInt::New();
6649 int *retPtr=ret->getPointer();
6650 const int *connI=_nodal_connec_index->getConstPointer();
6651 const int *conn=_nodal_connec->getConstPointer();
6652 int nbOfCells=getNumberOfCells();
6655 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6657 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6658 int offset=(int)std::distance(connI,i);
6659 if(code[3*kk+2]==-1)
6661 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6662 std::size_t pos2=std::distance(i,j);
6663 for(std::size_t k=0;k<pos2;k++)
6664 *retPtr++=(int)k+offset;
6669 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6670 retPtr,std::bind2nd(std::plus<int>(),offset));
6677 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6678 * 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.
6679 * 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.
6680 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6682 * \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.
6683 * \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,
6684 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6685 * \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.
6686 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6687 * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
6689 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6692 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6693 if(profile->getNumberOfComponents()!=1)
6694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6695 checkConnectivityFullyDefined();
6696 const int *conn=_nodal_connec->getConstPointer();
6697 const int *connI=_nodal_connec_index->getConstPointer();
6698 int nbOfCells=getNumberOfCells();
6699 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6700 std::vector<int> typeRangeVals(1);
6701 for(const int *i=connI;i!=connI+nbOfCells;)
6703 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6704 if(std::find(types.begin(),types.end(),curType)!=types.end())
6706 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6708 types.push_back(curType);
6709 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6710 typeRangeVals.push_back((int)std::distance(connI,i));
6713 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6714 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6715 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6717 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6719 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6720 code.resize(3*nbOfCastsFinal);
6721 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6722 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6723 for(int i=0;i<nbOfCastsFinal;i++)
6725 int castId=castsPresent->getIJ(i,0);
6726 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6727 idsInPflPerType2.push_back(tmp3);
6728 code[3*i]=(int)types[castId];
6729 code[3*i+1]=tmp3->getNumberOfTuples();
6730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6731 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6733 tmp4->copyStringInfoFrom(*profile);
6734 idsPerType2.push_back(tmp4);
6735 code[3*i+2]=(int)idsPerType2.size()-1;
6742 std::size_t sz2=idsInPflPerType2.size();
6743 idsInPflPerType.resize(sz2);
6744 for(std::size_t i=0;i<sz2;i++)
6746 DataArrayInt *locDa=idsInPflPerType2[i];
6748 idsInPflPerType[i]=locDa;
6750 std::size_t sz=idsPerType2.size();
6751 idsPerType.resize(sz);
6752 for(std::size_t i=0;i<sz;i++)
6754 DataArrayInt *locDa=idsPerType2[i];
6756 idsPerType[i]=locDa;
6761 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6762 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6763 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6764 * 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.
6766 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6768 checkFullyDefined();
6769 nM1LevMesh->checkFullyDefined();
6770 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6772 if(_coords!=nM1LevMesh->getCoords())
6773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6776 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6778 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6779 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6780 tmp->setConnectivity(tmp0,tmp1);
6781 tmp->renumberCells(ret0->getConstPointer(),false);
6782 revDesc=tmp->getNodalConnectivity();
6783 revDescIndx=tmp->getNodalConnectivityIndex();
6784 DataArrayInt *ret=0;
6785 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6788 ret->getMaxValue(tmp2);
6790 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6791 throw INTERP_KERNEL::Exception(oss.str().c_str());
6796 revDescIndx->incrRef();
6799 meshnM1Old2New=ret0;
6804 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6805 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6806 * in "Old to New" mode.
6807 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6808 * this array using decrRef() as it is no more needed.
6809 * \throw If the nodal connectivity of cells is not defined.
6811 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6813 checkConnectivityFullyDefined();
6814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6815 renumberCells(ret->getConstPointer(),false);
6820 * This methods checks that cells are sorted by their types.
6821 * This method makes asumption (no check) that connectivity is correctly set before calling.
6823 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6825 checkFullyDefined();
6826 const int *conn=_nodal_connec->getConstPointer();
6827 const int *connI=_nodal_connec_index->getConstPointer();
6828 int nbOfCells=getNumberOfCells();
6829 std::set<INTERP_KERNEL::NormalizedCellType> types;
6830 for(const int *i=connI;i!=connI+nbOfCells;)
6832 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6833 if(types.find(curType)!=types.end())
6835 types.insert(curType);
6836 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6842 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6843 * The geometric type order is specified by MED file.
6845 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6847 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6849 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6853 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6854 * that the order is specified in array defined by [orderBg,orderEnd).
6855 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6856 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6858 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6860 checkFullyDefined();
6861 const int *conn=_nodal_connec->getConstPointer();
6862 const int *connI=_nodal_connec_index->getConstPointer();
6863 int nbOfCells=getNumberOfCells();
6867 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6868 for(const int *i=connI;i!=connI+nbOfCells;)
6870 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6871 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6872 if(isTypeExists!=orderEnd)
6874 int pos=(int)std::distance(orderBg,isTypeExists);
6878 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6882 if(sg.find(curType)==sg.end())
6884 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6895 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6896 * 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
6897 * 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'.
6899 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6901 checkConnectivityFullyDefined();
6902 int nbOfCells=getNumberOfCells();
6903 const int *conn=_nodal_connec->getConstPointer();
6904 const int *connI=_nodal_connec_index->getConstPointer();
6905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6907 tmpa->alloc(nbOfCells,1);
6908 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6909 tmpb->fillWithZero();
6910 int *tmp=tmpa->getPointer();
6911 int *tmp2=tmpb->getPointer();
6912 for(const int *i=connI;i!=connI+nbOfCells;i++)
6914 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6917 int pos=(int)std::distance(orderBg,where);
6919 tmp[std::distance(connI,i)]=pos;
6923 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6924 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6925 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6926 throw INTERP_KERNEL::Exception(oss.str().c_str());
6929 nbPerType=tmpb.retn();
6934 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6936 * \return a new object containing the old to new correspondance.
6938 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6940 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6942 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6946 * 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 \a this.
6947 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6948 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6949 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6951 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6953 DataArrayInt *nbPerType=0;
6954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6955 nbPerType->decrRef();
6956 return tmpa->buildPermArrPerLevel();
6960 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6961 * The number of cells remains unchanged after the call of this method.
6962 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6963 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6965 * \return the array giving the correspondance old to new.
6967 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6969 checkFullyDefined();
6971 const int *conn=_nodal_connec->getConstPointer();
6972 const int *connI=_nodal_connec_index->getConstPointer();
6973 int nbOfCells=getNumberOfCells();
6974 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6975 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6976 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6978 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6979 types.push_back(curType);
6980 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6982 DataArrayInt *ret=DataArrayInt::New();
6983 ret->alloc(nbOfCells,1);
6984 int *retPtr=ret->getPointer();
6985 std::fill(retPtr,retPtr+nbOfCells,-1);
6987 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6989 for(const int *i=connI;i!=connI+nbOfCells;i++)
6990 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6991 retPtr[std::distance(connI,i)]=newCellId++;
6993 renumberCells(retPtr,false);
6998 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6999 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7000 * This method makes asumption that connectivity is correctly set before calling.
7002 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7004 checkFullyDefined();
7005 const int *conn=_nodal_connec->getConstPointer();
7006 const int *connI=_nodal_connec_index->getConstPointer();
7007 int nbOfCells=getNumberOfCells();
7008 std::vector<MEDCouplingUMesh *> ret;
7009 for(const int *i=connI;i!=connI+nbOfCells;)
7011 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7012 int beginCellId=(int)std::distance(connI,i);
7013 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7014 int endCellId=(int)std::distance(connI,i);
7015 int sz=endCellId-beginCellId;
7016 int *cells=new int[sz];
7017 for(int j=0;j<sz;j++)
7018 cells[j]=beginCellId+j;
7019 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7027 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7028 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7029 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7030 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7031 * are not used here to avoid the build of big permutation array.
7033 * \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
7034 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7035 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7036 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7037 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7038 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7039 * \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
7040 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7042 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7043 DataArrayInt *&szOfCellGrpOfSameType,
7044 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7046 std::vector<const MEDCouplingUMesh *> ms2;
7047 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7050 (*it)->checkConnectivityFullyDefined();
7054 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7055 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7056 int meshDim=ms2[0]->getMeshDimension();
7057 std::vector<const MEDCouplingUMesh *> m1ssm;
7058 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7060 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7061 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7064 ret1->alloc(0,1); ret2->alloc(0,1);
7065 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7067 if(meshDim!=(*it)->getMeshDimension())
7068 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7069 if(refCoo!=(*it)->getCoords())
7070 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7071 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7072 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7073 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7074 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7076 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7077 m1ssmSingleAuto.push_back(singleCell);
7078 m1ssmSingle.push_back(singleCell);
7079 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7082 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7084 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7085 for(std::size_t i=0;i<m1ssm.size();i++)
7086 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7087 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7088 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7089 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7094 * This method returns a newly created DataArrayInt instance.
7095 * This method retrieves cell ids in [begin,end) that have the type 'type'.
7097 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
7099 checkFullyDefined();
7100 const int *conn=_nodal_connec->getConstPointer();
7101 const int *connIndex=_nodal_connec_index->getConstPointer();
7102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7103 for(const int *w=begin;w!=end;w++)
7104 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7105 ret->pushBackSilent(*w);
7110 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7111 * are in [0:getNumberOfCells())
7113 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
7115 checkFullyDefined();
7116 const int *conn=_nodal_connec->getConstPointer();
7117 const int *connI=_nodal_connec_index->getConstPointer();
7118 int nbOfCells=getNumberOfCells();
7119 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
7120 int *tmp=new int[nbOfCells];
7121 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7124 for(const int *i=connI;i!=connI+nbOfCells;i++)
7125 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7126 tmp[std::distance(connI,i)]=j++;
7128 DataArrayInt *ret=DataArrayInt::New();
7129 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7130 ret->copyStringInfoFrom(*da);
7131 int *retPtr=ret->getPointer();
7132 const int *daPtr=da->getConstPointer();
7133 int nbOfElems=da->getNbOfElems();
7134 for(int k=0;k<nbOfElems;k++)
7135 retPtr[k]=tmp[daPtr[k]];
7141 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7142 * This method \b works \b for mesh sorted by type.
7143 * cells whose ids is in 'idsPerGeoType' array.
7144 * This method conserves coords and name of mesh.
7146 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7148 std::vector<int> code=getDistributionOfTypes();
7149 std::size_t nOfTypesInThis=code.size()/3;
7150 int sz=0,szOfType=0;
7151 for(std::size_t i=0;i<nOfTypesInThis;i++)
7156 szOfType=code[3*i+1];
7158 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7159 if(*work<0 || *work>=szOfType)
7161 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7162 oss << ". It should be in [0," << szOfType << ") !";
7163 throw INTERP_KERNEL::Exception(oss.str().c_str());
7165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7166 int *idsPtr=idsTokeep->getPointer();
7168 for(std::size_t i=0;i<nOfTypesInThis;i++)
7171 for(int j=0;j<code[3*i+1];j++)
7174 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7175 offset+=code[3*i+1];
7177 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7178 ret->copyTinyInfoFrom(this);
7183 * This method returns a vector of size 'this->getNumberOfCells()'.
7184 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7186 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7188 int ncell=getNumberOfCells();
7189 std::vector<bool> ret(ncell);
7190 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7191 const int *c=getNodalConnectivity()->getConstPointer();
7192 for(int i=0;i<ncell;i++)
7194 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7195 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7196 ret[i]=cm.isQuadratic();
7202 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7204 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7206 if(other->getType()!=UNSTRUCTURED)
7207 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7208 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7209 return MergeUMeshes(this,otherC);
7213 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7214 * computed by averaging coordinates of cell nodes, so this method is not a right
7215 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7216 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7217 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7218 * components. The caller is to delete this array using decrRef() as it is
7220 * \throw If the coordinates array is not set.
7221 * \throw If the nodal connectivity of cells is not defined.
7222 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7224 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7226 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7227 int spaceDim=getSpaceDimension();
7228 int nbOfCells=getNumberOfCells();
7229 ret->alloc(nbOfCells,spaceDim);
7230 ret->copyStringInfoFrom(*getCoords());
7231 double *ptToFill=ret->getPointer();
7232 const int *nodal=_nodal_connec->getConstPointer();
7233 const int *nodalI=_nodal_connec_index->getConstPointer();
7234 const double *coor=_coords->getConstPointer();
7235 for(int i=0;i<nbOfCells;i++)
7237 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7238 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7245 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7246 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7248 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7249 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7251 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7252 * \throw If \a this is not fully defined (coordinates and connectivity)
7253 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7255 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7257 checkFullyDefined();
7258 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7259 int spaceDim=getSpaceDimension();
7260 int nbOfCells=getNumberOfCells();
7261 int nbOfNodes=getNumberOfNodes();
7262 ret->alloc(nbOfCells,spaceDim);
7263 double *ptToFill=ret->getPointer();
7264 const int *nodal=_nodal_connec->getConstPointer();
7265 const int *nodalI=_nodal_connec_index->getConstPointer();
7266 const double *coor=_coords->getConstPointer();
7267 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7269 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7270 std::fill(ptToFill,ptToFill+spaceDim,0.);
7271 if(type!=INTERP_KERNEL::NORM_POLYHED)
7273 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7275 if(*conn>=0 && *conn<nbOfNodes)
7276 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7279 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7280 throw INTERP_KERNEL::Exception(oss.str().c_str());
7283 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7284 if(nbOfNodesInCell>0)
7285 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7288 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7289 throw INTERP_KERNEL::Exception(oss.str().c_str());
7294 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7296 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7298 if(*it>=0 && *it<nbOfNodes)
7299 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7302 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7303 throw INTERP_KERNEL::Exception(oss.str().c_str());
7307 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7310 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7311 throw INTERP_KERNEL::Exception(oss.str().c_str());
7319 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7320 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7321 * are specified via an array of cell ids.
7322 * \warning Validity of the specified cell ids is not checked!
7323 * Valid range is [ 0, \a this->getNumberOfCells() ).
7324 * \param [in] begin - an array of cell ids of interest.
7325 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7326 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7327 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7328 * caller is to delete this array using decrRef() as it is no more needed.
7329 * \throw If the coordinates array is not set.
7330 * \throw If the nodal connectivity of cells is not defined.
7332 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7333 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7335 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7337 DataArrayDouble *ret=DataArrayDouble::New();
7338 int spaceDim=getSpaceDimension();
7339 int nbOfTuple=(int)std::distance(begin,end);
7340 ret->alloc(nbOfTuple,spaceDim);
7341 double *ptToFill=ret->getPointer();
7342 double *tmp=new double[spaceDim];
7343 const int *nodal=_nodal_connec->getConstPointer();
7344 const int *nodalI=_nodal_connec_index->getConstPointer();
7345 const double *coor=_coords->getConstPointer();
7346 for(const int *w=begin;w!=end;w++)
7348 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7349 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7357 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7360 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7363 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7364 da->checkAllocated();
7365 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7367 int nbOfTuples=da->getNumberOfTuples();
7368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7370 c->alloc(2*nbOfTuples,1);
7371 cI->alloc(nbOfTuples+1,1);
7372 int *cp=c->getPointer();
7373 int *cip=cI->getPointer();
7375 for(int i=0;i<nbOfTuples;i++)
7377 *cp++=INTERP_KERNEL::NORM_POINT1;
7381 ret->setConnectivity(c,cI,true);
7385 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7386 * Cells and nodes of
7387 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7388 * \param [in] mesh1 - the first mesh.
7389 * \param [in] mesh2 - the second mesh.
7390 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7391 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7392 * is no more needed.
7393 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7394 * \throw If the coordinates array is not set in none of the meshes.
7395 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7396 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7398 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7400 std::vector<const MEDCouplingUMesh *> tmp(2);
7401 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7402 return MergeUMeshes(tmp);
7406 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7407 * Cells and nodes of
7408 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7409 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7410 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7411 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7412 * is no more needed.
7413 * \throw If \a a.size() == 0.
7414 * \throw If \a a[ *i* ] == NULL.
7415 * \throw If the coordinates array is not set in none of the meshes.
7416 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7417 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7419 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7421 std::size_t sz=a.size();
7423 return MergeUMeshesLL(a);
7424 for(std::size_t ii=0;ii<sz;ii++)
7427 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7428 throw INTERP_KERNEL::Exception(oss.str().c_str());
7430 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7431 std::vector< const MEDCouplingUMesh * > aa(sz);
7433 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7435 const MEDCouplingUMesh *cur=a[i];
7436 const DataArrayDouble *coo=cur->getCoords();
7438 spaceDim=coo->getNumberOfComponents();
7441 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7442 for(std::size_t i=0;i<sz;i++)
7444 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7447 return MergeUMeshesLL(aa);
7452 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7455 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7456 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7457 int meshDim=(*it)->getMeshDimension();
7458 int nbOfCells=(*it)->getNumberOfCells();
7459 int meshLgth=(*it++)->getMeshLength();
7460 for(;it!=a.end();it++)
7462 if(meshDim!=(*it)->getMeshDimension())
7463 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7464 nbOfCells+=(*it)->getNumberOfCells();
7465 meshLgth+=(*it)->getMeshLength();
7467 std::vector<const MEDCouplingPointSet *> aps(a.size());
7468 std::copy(a.begin(),a.end(),aps.begin());
7469 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7470 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7471 ret->setCoords(pts);
7472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7473 c->alloc(meshLgth,1);
7474 int *cPtr=c->getPointer();
7475 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7476 cI->alloc(nbOfCells+1,1);
7477 int *cIPtr=cI->getPointer();
7481 for(it=a.begin();it!=a.end();it++)
7483 int curNbOfCell=(*it)->getNumberOfCells();
7484 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7485 const int *curC=(*it)->_nodal_connec->getConstPointer();
7486 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7487 for(int j=0;j<curNbOfCell;j++)
7489 const int *src=curC+curCI[j];
7491 for(;src!=curC+curCI[j+1];src++,cPtr++)
7499 offset+=curCI[curNbOfCell];
7500 offset2+=(*it)->getNumberOfNodes();
7503 ret->setConnectivity(c,cI,true);
7510 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7511 * dimension and sharing the node coordinates array.
7512 * All cells of the first mesh precede all cells of the second mesh
7513 * within the result mesh.
7514 * \param [in] mesh1 - the first mesh.
7515 * \param [in] mesh2 - the second mesh.
7516 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7517 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7518 * is no more needed.
7519 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7520 * \throw If the meshes do not share the node coordinates array.
7521 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7522 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7524 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7526 std::vector<const MEDCouplingUMesh *> tmp(2);
7527 tmp[0]=mesh1; tmp[1]=mesh2;
7528 return MergeUMeshesOnSameCoords(tmp);
7532 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7533 * dimension and sharing the node coordinates array.
7534 * All cells of the *i*-th mesh precede all cells of the
7535 * (*i*+1)-th mesh within the result mesh.
7536 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7537 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7538 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7539 * is no more needed.
7540 * \throw If \a a.size() == 0.
7541 * \throw If \a a[ *i* ] == NULL.
7542 * \throw If the meshes do not share the node coordinates array.
7543 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7544 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7546 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7549 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7550 for(std::size_t ii=0;ii<meshes.size();ii++)
7553 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7554 throw INTERP_KERNEL::Exception(oss.str().c_str());
7556 const DataArrayDouble *coords=meshes.front()->getCoords();
7557 int meshDim=meshes.front()->getMeshDimension();
7558 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7560 int meshIndexLgth=0;
7561 for(;iter!=meshes.end();iter++)
7563 if(coords!=(*iter)->getCoords())
7564 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7565 if(meshDim!=(*iter)->getMeshDimension())
7566 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7567 meshLgth+=(*iter)->getMeshLength();
7568 meshIndexLgth+=(*iter)->getNumberOfCells();
7570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7571 nodal->alloc(meshLgth,1);
7572 int *nodalPtr=nodal->getPointer();
7573 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7574 nodalIndex->alloc(meshIndexLgth+1,1);
7575 int *nodalIndexPtr=nodalIndex->getPointer();
7577 for(iter=meshes.begin();iter!=meshes.end();iter++)
7579 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7580 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7581 int nbOfCells=(*iter)->getNumberOfCells();
7582 int meshLgth2=(*iter)->getMeshLength();
7583 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7584 if(iter!=meshes.begin())
7585 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7587 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7590 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7591 ret->setName("merge");
7592 ret->setMeshDimension(meshDim);
7593 ret->setConnectivity(nodal,nodalIndex,true);
7594 ret->setCoords(coords);
7599 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7600 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7601 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7602 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7603 * New" mode are returned for each input mesh.
7604 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7605 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7606 * valid values [0,1,2], see zipConnectivityTraducer().
7607 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7608 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7609 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7611 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7612 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7613 * is no more needed.
7614 * \throw If \a meshes.size() == 0.
7615 * \throw If \a meshes[ *i* ] == NULL.
7616 * \throw If the meshes do not share the node coordinates array.
7617 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7618 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7619 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7620 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7622 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7624 //All checks are delegated to MergeUMeshesOnSameCoords
7625 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7627 corr.resize(meshes.size());
7628 std::size_t nbOfMeshes=meshes.size();
7630 const int *o2nPtr=o2n->getConstPointer();
7631 for(std::size_t i=0;i<nbOfMeshes;i++)
7633 DataArrayInt *tmp=DataArrayInt::New();
7634 int curNbOfCells=meshes[i]->getNumberOfCells();
7635 tmp->alloc(curNbOfCells,1);
7636 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7637 offset+=curNbOfCells;
7638 tmp->setName(meshes[i]->getName());
7645 * Makes all given meshes share the nodal connectivity array. The common connectivity
7646 * array is created by concatenating the connectivity arrays of all given meshes. All
7647 * the given meshes must be of the same space dimension but dimension of cells **can
7648 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7649 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7650 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7651 * \param [in,out] meshes - a vector of meshes to update.
7652 * \throw If any of \a meshes is NULL.
7653 * \throw If the coordinates array is not set in any of \a meshes.
7654 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7655 * \throw If \a meshes are of different space dimension.
7657 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7659 std::size_t sz=meshes.size();
7662 std::vector< const DataArrayDouble * > coords(meshes.size());
7663 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7664 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7668 (*it)->checkConnectivityFullyDefined();
7669 const DataArrayDouble *coo=(*it)->getCoords();
7674 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7675 oss << " has no coordinate array defined !";
7676 throw INTERP_KERNEL::Exception(oss.str().c_str());
7681 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7682 oss << " is null !";
7683 throw INTERP_KERNEL::Exception(oss.str().c_str());
7686 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7687 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7688 int offset=(*it)->getNumberOfNodes();
7689 (*it++)->setCoords(res);
7690 for(;it!=meshes.end();it++)
7692 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7693 (*it)->setCoords(res);
7694 (*it)->shiftNodeNumbersInConn(offset);
7695 offset+=oldNumberOfNodes;
7700 * Merges nodes coincident with a given precision within all given meshes that share
7701 * the nodal connectivity array. The given meshes **can be of different** mesh
7702 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7703 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7704 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7705 * \param [in,out] meshes - a vector of meshes to update.
7706 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7707 * \throw If any of \a meshes is NULL.
7708 * \throw If the \a meshes do not share the same node coordinates array.
7709 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7711 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7715 std::set<const DataArrayDouble *> s;
7716 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7719 s.insert((*it)->getCoords());
7722 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 !";
7723 throw INTERP_KERNEL::Exception(oss.str().c_str());
7728 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 !";
7729 throw INTERP_KERNEL::Exception(oss.str().c_str());
7731 const DataArrayDouble *coo=*(s.begin());
7735 DataArrayInt *comm,*commI;
7736 coo->findCommonTuples(eps,-1,comm,commI);
7737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7738 int oldNbOfNodes=coo->getNumberOfTuples();
7740 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7741 if(oldNbOfNodes==newNbOfNodes)
7743 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7744 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7746 (*it)->renumberNodesInConn(o2n->getConstPointer());
7747 (*it)->setCoords(newCoords);
7752 * 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.
7753 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7754 * \param isQuad specifies the policy of connectivity.
7755 * @ret in/out parameter in which the result will be append
7757 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7759 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7760 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7761 ret.push_back(cm.getExtrudedType());
7762 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7765 case INTERP_KERNEL::NORM_POINT1:
7767 ret.push_back(connBg[1]);
7768 ret.push_back(connBg[1]+nbOfNodesPerLev);
7771 case INTERP_KERNEL::NORM_SEG2:
7773 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7774 ret.insert(ret.end(),conn,conn+4);
7777 case INTERP_KERNEL::NORM_SEG3:
7779 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7780 ret.insert(ret.end(),conn,conn+8);
7783 case INTERP_KERNEL::NORM_QUAD4:
7785 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7786 ret.insert(ret.end(),conn,conn+8);
7789 case INTERP_KERNEL::NORM_TRI3:
7791 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7792 ret.insert(ret.end(),conn,conn+6);
7795 case INTERP_KERNEL::NORM_TRI6:
7797 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,
7798 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7799 ret.insert(ret.end(),conn,conn+15);
7802 case INTERP_KERNEL::NORM_QUAD8:
7805 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7806 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7807 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7809 ret.insert(ret.end(),conn,conn+20);
7812 case INTERP_KERNEL::NORM_POLYGON:
7814 std::back_insert_iterator< std::vector<int> > ii(ret);
7815 std::copy(connBg+1,connEnd,ii);
7817 std::reverse_iterator<const int *> rConnBg(connEnd);
7818 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7819 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7820 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7821 for(std::size_t i=0;i<nbOfRadFaces;i++)
7824 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7825 std::copy(conn,conn+4,ii);
7830 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7835 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
7837 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7839 double v[3]={0.,0.,0.};
7840 std::size_t sz=std::distance(begin,end);
7843 for(std::size_t i=0;i<sz;i++)
7845 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];
7846 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7847 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7849 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7853 * The polyhedron is specfied by its connectivity nodes in [begin,end).
7855 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7857 std::vector<std::pair<int,int> > edges;
7858 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7859 const int *bgFace=begin;
7860 for(std::size_t i=0;i<nbOfFaces;i++)
7862 const int *endFace=std::find(bgFace+1,end,-1);
7863 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7864 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7866 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7867 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7869 edges.push_back(p1);
7873 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7877 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
7879 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7881 double vec0[3],vec1[3];
7882 std::size_t sz=std::distance(begin,end);
7884 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7885 int nbOfNodes=(int)sz/2;
7886 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7887 const double *pt0=coords+3*begin[0];
7888 const double *pt1=coords+3*begin[nbOfNodes];
7889 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7890 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7893 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7895 std::size_t sz=std::distance(begin,end);
7896 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7897 std::size_t nbOfNodes(sz/2);
7898 std::copy(begin,end,(int *)tmp);
7899 for(std::size_t j=1;j<nbOfNodes;j++)
7901 begin[j]=tmp[nbOfNodes-j];
7902 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7906 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7908 std::size_t sz=std::distance(begin,end);
7910 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7911 double vec0[3],vec1[3];
7912 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7913 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];
7914 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;
7917 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7919 std::size_t sz=std::distance(begin,end);
7921 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7923 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7924 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7925 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7929 * 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)
7930 * 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
7933 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7934 * \param [in] coords the coordinates with nb of components exactly equal to 3
7935 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7936 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7937 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7939 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7941 int nbFaces=std::count(begin+1,end,-1)+1;
7942 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7943 double *vPtr=v->getPointer();
7944 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7945 double *pPtr=p->getPointer();
7946 const int *stFaceConn=begin+1;
7947 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7949 const int *endFaceConn=std::find(stFaceConn,end,-1);
7950 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7951 stFaceConn=endFaceConn+1;
7953 pPtr=p->getPointer(); vPtr=v->getPointer();
7954 DataArrayInt *comm1=0,*commI1=0;
7955 v->findCommonTuples(eps,-1,comm1,commI1);
7956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7957 const int *comm1Ptr=comm1->getConstPointer();
7958 const int *commI1Ptr=commI1->getConstPointer();
7959 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7960 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7963 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7964 mm->finishInsertingCells();
7966 for(int i=0;i<nbOfGrps1;i++)
7968 int vecId=comm1Ptr[commI1Ptr[i]];
7969 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7970 DataArrayInt *comm2=0,*commI2=0;
7971 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7973 const int *comm2Ptr=comm2->getConstPointer();
7974 const int *commI2Ptr=commI2->getConstPointer();
7975 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7976 for(int j=0;j<nbOfGrps2;j++)
7978 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7980 res->insertAtTheEnd(begin,end);
7981 res->pushBackSilent(-1);
7985 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7987 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7988 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7989 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7990 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7991 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7992 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7993 const int *idsNodePtr=idsNode->getConstPointer();
7994 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];
7995 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7996 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7997 if(std::abs(norm)>eps)
7999 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8000 mm3->rotate(center,vec,angle);
8002 mm3->changeSpaceDimension(2);
8003 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8004 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8005 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8006 int nbOfCells=mm4->getNumberOfCells();
8007 for(int k=0;k<nbOfCells;k++)
8010 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8011 res->pushBackSilent(idsNodePtr[*work]);
8012 res->pushBackSilent(-1);
8017 res->popBackSilent();
8021 * 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
8022 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
8024 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8025 * \param [in] coords coordinates expected to have 3 components.
8026 * \param [in] begin start of the nodal connectivity of the face.
8027 * \param [in] end end of the nodal connectivity (excluded) of the face.
8028 * \param [out] v the normalized vector of size 3
8029 * \param [out] p the pos of plane
8031 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
8033 std::size_t nbPoints=std::distance(begin,end);
8035 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8036 double vec[3]={0.,0.,0.};
8038 bool refFound=false;
8039 for(;j<nbPoints-1 && !refFound;j++)
8041 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8042 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8043 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8044 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8048 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8051 for(std::size_t i=j;i<nbPoints-1;i++)
8054 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8055 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8056 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8057 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8060 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8061 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];
8062 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8065 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8066 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8070 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8074 * This method tries to obtain a well oriented polyhedron.
8075 * If the algorithm fails, an exception will be thrown.
8077 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
8079 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8080 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8081 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8083 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8084 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8085 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8087 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8090 std::size_t smthChanged=0;
8091 for(std::size_t i=0;i<nbOfFaces;i++)
8093 endFace=std::find(bgFace+1,end,-1);
8094 nbOfEdgesInFace=std::distance(bgFace,endFace);
8098 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8100 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8101 std::pair<int,int> p2(p1.second,p1.first);
8102 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8103 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8104 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8109 std::reverse(bgFace+1,endFace);
8110 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8112 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8113 std::pair<int,int> p2(p1.second,p1.first);
8114 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8115 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8116 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8117 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8118 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8119 if(it!=edgesOK.end())
8122 edgesFinished.push_back(p1);
8125 edgesOK.push_back(p1);
8132 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8134 if(!edgesOK.empty())
8135 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8136 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8137 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8139 for(std::size_t i=0;i<nbOfFaces;i++)
8141 endFace=std::find(bgFace+1,end,-1);
8142 std::reverse(bgFace+1,endFace);
8149 * This method makes the assumption spacedimension == meshdimension == 2.
8150 * This method works only for linear cells.
8152 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8154 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
8156 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8157 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8158 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8159 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8160 int nbOfNodesExpected=m->getNumberOfNodes();
8161 if(m->getNumberOfCells()!=nbOfNodesExpected)
8162 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8164 const int *n2oPtr=n2o->getConstPointer();
8165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8166 m->getReverseNodalConnectivity(revNodal,revNodalI);
8167 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8168 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8169 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8170 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8171 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
8172 if(nbOfNodesExpected<1)
8175 int prevNode=nodalPtr[nodalIPtr[0]+1];
8176 *work++=n2oPtr[prevNode];
8177 for(int i=1;i<nbOfNodesExpected;i++)
8179 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8181 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8182 conn.erase(prevNode);
8185 int curNode=*(conn.begin());
8186 *work++=n2oPtr[curNode];
8187 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8188 shar.erase(prevCell);
8191 prevCell=*(shar.begin());
8195 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8198 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8201 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8207 * This method makes the assumption spacedimension == meshdimension == 3.
8208 * This method works only for linear cells.
8210 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8212 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8214 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8215 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8216 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8217 const int *conn=m->getNodalConnectivity()->getConstPointer();
8218 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8219 int nbOfCells=m->getNumberOfCells();
8220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8221 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8224 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8225 for(int i=1;i<nbOfCells;i++)
8228 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8234 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8235 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8237 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8241 for(int i=0;i<nbOfNodesInCell;i++)
8242 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8243 else if(spaceDim==2)
8245 for(int i=0;i<nbOfNodesInCell;i++)
8247 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8252 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8255 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8257 int nbOfCells=getNumberOfCells();
8259 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8260 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};
8261 ofs << " <" << getVTKDataSetType() << ">\n";
8262 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8263 ofs << " <PointData>\n" << pointData << std::endl;
8264 ofs << " </PointData>\n";
8265 ofs << " <CellData>\n" << cellData << std::endl;
8266 ofs << " </CellData>\n";
8267 ofs << " <Points>\n";
8268 if(getSpaceDimension()==3)
8269 _coords->writeVTK(ofs,8,"Points");
8272 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8273 coo->writeVTK(ofs,8,"Points");
8275 ofs << " </Points>\n";
8276 ofs << " <Cells>\n";
8277 const int *cPtr=_nodal_connec->getConstPointer();
8278 const int *cIPtr=_nodal_connec_index->getConstPointer();
8279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8283 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8284 int szFaceOffsets=0,szConn=0;
8285 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8288 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8291 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8292 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8296 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8297 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8298 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8299 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8300 w4=std::copy(c.begin(),c.end(),w4);
8303 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8304 types->writeVTK(ofs,8,"UInt8","types");
8305 offsets->writeVTK(ofs,8,"Int32","offsets");
8306 if(szFaceOffsets!=0)
8307 {//presence of Polyhedra
8308 connectivity->reAlloc(szConn);
8309 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8311 w1=faces->getPointer();
8312 for(int i=0;i<nbOfCells;i++)
8313 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8315 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8317 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8318 for(int j=0;j<nbFaces;j++)
8320 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8321 *w1++=(int)std::distance(w6,w5);
8322 w1=std::copy(w6,w5,w1);
8326 faces->writeVTK(ofs,8,"Int32","faces");
8328 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8329 ofs << " </Cells>\n";
8330 ofs << " </Piece>\n";
8331 ofs << " </" << getVTKDataSetType() << ">\n";
8334 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8336 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8338 { stream << " Not set !"; return ; }
8339 stream << " Mesh dimension : " << _mesh_dim << ".";
8343 { stream << " No coordinates set !"; return ; }
8344 if(!_coords->isAllocated())
8345 { stream << " Coordinates set but not allocated !"; return ; }
8346 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8347 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8348 if(!_nodal_connec_index)
8349 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8350 if(!_nodal_connec_index->isAllocated())
8351 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8352 int lgth=_nodal_connec_index->getNumberOfTuples();
8353 int cpt=_nodal_connec_index->getNumberOfComponents();
8354 if(cpt!=1 || lgth<1)
8356 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8359 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8361 return std::string("UnstructuredGrid");
8365 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8366 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8367 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8369 * \param [in] m1 - the first input mesh which is a partitioned object.
8370 * \param [in] m2 - the second input mesh which is a partition tool.
8371 * \param [in] eps - precision used to detect coincident mesh entities.
8372 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8373 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8374 * this array using decrRef() as it is no more needed.
8375 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8376 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8377 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8378 * any cell of \a m2. The caller is to delete this array using decrRef() as
8379 * it is no more needed.
8380 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8381 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8382 * is no more needed.
8383 * \throw If the coordinates array is not set in any of the meshes.
8384 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8385 * \throw If any of the meshes is not a 2D mesh in 2D space.
8387 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8389 m1->checkFullyDefined();
8390 m2->checkFullyDefined();
8391 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8392 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8393 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8394 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8395 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8396 std::vector<double> addCoo,addCoordsQuadratic;
8397 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8398 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8399 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8400 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8401 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8403 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8404 std::vector< std::vector<int> > intersectEdge2;
8405 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8406 subDiv2.clear(); dd5=0; dd6=0;
8407 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8408 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8409 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8410 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8412 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8413 addCooDa->alloc((int)(addCoo.size())/2,2);
8414 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8415 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8416 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8417 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8418 std::vector<const DataArrayDouble *> coordss(4);
8419 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8420 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8421 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8422 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8423 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8426 ret->setConnectivity(conn,connI,true);
8427 ret->setCoords(coo);
8428 cellNb1=c1.retn(); cellNb2=c2.retn();
8432 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8433 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8434 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8435 const std::vector<double>& addCoords,
8436 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8438 static const int SPACEDIM=2;
8439 std::vector<double> bbox1,bbox2;
8440 const double *coo1=m1->getCoords()->getConstPointer();
8441 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8442 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8443 int offset1=m1->getNumberOfNodes();
8444 const double *coo2=m2->getCoords()->getConstPointer();
8445 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8446 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8447 int offset2=offset1+m2->getNumberOfNodes();
8448 int offset3=offset2+((int)addCoords.size())/2;
8449 m1->getBoundingBoxForBBTree(bbox1);
8450 m2->getBoundingBoxForBBTree(bbox2);
8451 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8452 int ncell1=m1->getNumberOfCells();
8454 for(int i=0;i<ncell1;i++)
8456 std::vector<int> candidates2;
8457 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8458 std::map<INTERP_KERNEL::Node *,int> mapp;
8459 std::map<int,INTERP_KERNEL::Node *> mappRev;
8460 INTERP_KERNEL::QuadraticPolygon pol1;
8461 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8462 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8463 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8464 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8465 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8467 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
8468 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8469 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8470 for(it1.first();!it1.finished();it1.next())
8471 edges1.insert(it1.current()->getPtr());
8473 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8474 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8476 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8478 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8479 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8480 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8481 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8482 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8485 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8487 pol1.initLocationsWithOther(pol2s[ii]);
8488 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8489 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8490 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8496 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8498 catch(INTERP_KERNEL::Exception& e)
8500 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();
8501 throw INTERP_KERNEL::Exception(oss.str().c_str());
8504 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8505 (*it).second->decrRef();
8510 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8513 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8514 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8515 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8516 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8517 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8519 static const int SPACEDIM=2;
8520 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8521 desc2=DataArrayInt::New();
8522 descIndx2=DataArrayInt::New();
8523 revDesc2=DataArrayInt::New();
8524 revDescIndx2=DataArrayInt::New();
8525 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8526 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8527 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8528 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8529 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8530 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8531 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8532 std::vector<double> bbox1,bbox2;
8533 m1Desc->getBoundingBoxForBBTree(bbox1);
8534 m2Desc->getBoundingBoxForBBTree(bbox2);
8535 int ncell1=m1Desc->getNumberOfCells();
8536 int ncell2=m2Desc->getNumberOfCells();
8537 intersectEdge1.resize(ncell1);
8538 colinear2.resize(ncell2);
8539 subDiv2.resize(ncell2);
8540 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8541 std::vector<int> candidates1(1);
8542 int offset1=m1->getNumberOfNodes();
8543 int offset2=offset1+m2->getNumberOfNodes();
8544 for(int i=0;i<ncell1;i++)
8546 std::vector<int> candidates2;
8547 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8548 if(!candidates2.empty())
8550 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8551 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8553 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8554 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8559 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8561 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8562 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8566 * This method performs the 2nd step of Partition of 2D mesh.
8567 * This method has 4 inputs :
8568 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8569 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8570 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8571 * 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'
8572 * \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'
8573 * \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.
8574 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8576 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)
8578 int offset1=m1->getNumberOfNodes();
8579 int ncell=m2->getNumberOfCells();
8580 const int *c=m2->getNodalConnectivity()->getConstPointer();
8581 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8582 const double *coo=m2->getCoords()->getConstPointer();
8583 const double *cooBis=m1->getCoords()->getConstPointer();
8584 int offset2=offset1+m2->getNumberOfNodes();
8585 intersectEdge.resize(ncell);
8586 for(int i=0;i<ncell;i++,cI++)
8588 const std::vector<int>& divs=subDiv[i];
8589 int nnode=cI[1]-cI[0]-1;
8590 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8591 std::map<INTERP_KERNEL::Node *, int> mapp22;
8592 for(int j=0;j<nnode;j++)
8594 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8595 int nnid=c[(*cI)+j+1];
8596 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8597 mapp22[nn]=nnid+offset1;
8599 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8600 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8601 ((*it).second.first)->decrRef();
8602 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8603 std::map<INTERP_KERNEL::Node *,int> mapp3;
8604 for(std::size_t j=0;j<divs.size();j++)
8607 INTERP_KERNEL::Node *tmp=0;
8609 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8611 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8613 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8617 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8618 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8625 * 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).
8626 * 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
8627 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8628 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8629 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8630 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8631 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8632 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8633 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8634 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8635 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8636 * \param [out] cut3DSuf input/output param.
8638 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8639 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8640 const int *desc, const int *descIndx,
8641 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8643 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8644 int nbOf3DSurfCell=(int)cut3DSurf.size();
8645 for(int i=0;i<nbOf3DSurfCell;i++)
8647 std::vector<int> res;
8648 int offset=descIndx[i];
8649 int nbOfSeg=descIndx[i+1]-offset;
8650 for(int j=0;j<nbOfSeg;j++)
8652 int edgeId=desc[offset+j];
8653 int status=cut3DCurve[edgeId];
8657 res.push_back(status);
8660 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8661 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8669 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8675 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8676 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8679 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8683 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8688 {// case when plane is on a multi colinear edge of a polyhedron
8689 if((int)res.size()==2*nbOfSeg)
8691 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8701 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8702 * 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).
8703 * 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
8704 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8705 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8706 * \param desc is the descending connectivity 3D->3DSurf
8707 * \param descIndx is the descending connectivity index 3D->3DSurf
8709 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8710 const int *desc, const int *descIndx,
8711 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8713 checkFullyDefined();
8714 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8715 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8716 const int *nodal3D=_nodal_connec->getConstPointer();
8717 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8718 int nbOfCells=getNumberOfCells();
8719 for(int i=0;i<nbOfCells;i++)
8721 std::map<int, std::set<int> > m;
8722 int offset=descIndx[i];
8723 int nbOfFaces=descIndx[i+1]-offset;
8726 for(int j=0;j<nbOfFaces;j++)
8728 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8729 if(p.first!=-1 && p.second!=-1)
8733 start=p.first; end=p.second;
8734 m[p.first].insert(p.second);
8735 m[p.second].insert(p.first);
8739 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8740 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8741 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8742 INTERP_KERNEL::NormalizedCellType cmsId;
8743 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8744 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8745 for(unsigned k=0;k<nbOfNodesSon;k++)
8747 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8748 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8755 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8759 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8760 const std::set<int>& s=(*it).second;
8761 std::set<int> s2; s2.insert(prev);
8763 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8766 int val=*s3.begin();
8767 conn.push_back(start);
8774 conn.push_back(end);
8777 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8778 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8779 cellIds->pushBackSilent(i);
8785 * 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
8786 * 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
8787 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8788 * 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
8789 * 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.
8791 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8793 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8795 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8798 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8799 if(cm.getDimension()==2)
8801 const int *node=nodalConnBg+1;
8802 int startNode=*node++;
8803 double refX=coords[2*startNode];
8804 for(;node!=nodalConnEnd;node++)
8806 if(coords[2*(*node)]<refX)
8809 refX=coords[2*startNode];
8812 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8816 double angle0=-M_PI/2;
8821 double angleNext=0.;
8822 while(nextNode!=startNode)
8826 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8828 if(*node!=tmpOut.back() && *node!=prevNode)
8830 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8831 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8836 res=angle0-angleM+2.*M_PI;
8845 if(nextNode!=startNode)
8847 angle0=angleNext-M_PI;
8850 prevNode=tmpOut.back();
8851 tmpOut.push_back(nextNode);
8854 std::vector<int> tmp3(2*(sz-1));
8855 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8856 std::copy(nodalConnBg+1,nodalConnEnd,it);
8857 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8859 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8862 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8864 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8869 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8870 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8875 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8882 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8883 * 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.
8885 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8886 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8887 * \param [in,out] arr array in which the remove operation will be done.
8888 * \param [in,out] arrIndx array in the remove operation will modify
8889 * \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])
8890 * \return true if \b arr and \b arrIndx have been modified, false if not.
8892 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8894 if(!arrIndx || !arr)
8895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8896 if(offsetForRemoval<0)
8897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8898 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8899 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8900 int *arrIPtr=arrIndx->getPointer();
8903 const int *arrPtr=arr->getConstPointer();
8904 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8905 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8907 if(*arrIPtr-previousArrI>offsetForRemoval)
8909 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8911 if(s.find(*work)==s.end())
8912 arrOut.push_back(*work);
8915 previousArrI=*arrIPtr;
8916 *arrIPtr=(int)arrOut.size();
8918 if(arr->getNumberOfTuples()==(int)arrOut.size())
8920 arr->alloc((int)arrOut.size(),1);
8921 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8926 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8927 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8928 * The selection of extraction is done standardly in new2old format.
8929 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8931 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8932 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8933 * \param [in] arrIn arr origin array from which the extraction will be done.
8934 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8935 * \param [out] arrOut the resulting array
8936 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8938 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8939 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8941 if(!arrIn || !arrIndxIn)
8942 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8943 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8944 const int *arrInPtr=arrIn->getConstPointer();
8945 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8946 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8947 int maxSizeOfArr=arrIn->getNumberOfTuples();
8948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8949 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8950 arrIo->alloc((int)(sz+1),1);
8951 const int *idsIt=idsOfSelectBg;
8952 int *work=arrIo->getPointer();
8955 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8957 if(*idsIt>=0 && *idsIt<nbOfGrps)
8958 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8961 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8962 throw INTERP_KERNEL::Exception(oss.str().c_str());
8968 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8969 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8970 throw INTERP_KERNEL::Exception(oss.str().c_str());
8973 arro->alloc(lgth,1);
8974 work=arro->getPointer();
8975 idsIt=idsOfSelectBg;
8976 for(std::size_t i=0;i<sz;i++,idsIt++)
8978 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8979 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8982 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8983 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8984 throw INTERP_KERNEL::Exception(oss.str().c_str());
8988 arrIndexOut=arrIo.retn();
8992 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8993 * 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
8994 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8995 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8997 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8998 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8999 * \param [in] arrIn arr origin array from which the extraction will be done.
9000 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9001 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9002 * \param [in] srcArrIndex index array of \b srcArr
9003 * \param [out] arrOut the resulting array
9004 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9006 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9008 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9009 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9010 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9012 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9013 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9016 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9017 std::vector<bool> v(nbOfTuples,true);
9019 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9020 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9021 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9023 if(*it>=0 && *it<nbOfTuples)
9026 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9030 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9031 throw INTERP_KERNEL::Exception(oss.str().c_str());
9034 srcArrIndexPtr=srcArrIndex->getConstPointer();
9035 arrIo->alloc(nbOfTuples+1,1);
9036 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9037 const int *arrInPtr=arrIn->getConstPointer();
9038 const int *srcArrPtr=srcArr->getConstPointer();
9039 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9040 int *arroPtr=arro->getPointer();
9041 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9045 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9046 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9050 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9051 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9052 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9056 arrIndexOut=arrIo.retn();
9060 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9061 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9063 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9064 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9065 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9066 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9067 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9068 * \param [in] srcArrIndex index array of \b srcArr
9070 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9072 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9073 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9075 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9076 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9077 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9078 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9079 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9080 int *arrInOutPtr=arrInOut->getPointer();
9081 const int *srcArrPtr=srcArr->getConstPointer();
9082 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9084 if(*it>=0 && *it<nbOfTuples)
9086 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9087 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9090 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] !";
9091 throw INTERP_KERNEL::Exception(oss.str().c_str());
9096 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9097 throw INTERP_KERNEL::Exception(oss.str().c_str());
9103 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9104 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9105 * 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]].
9106 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9107 * A negative value in \b arrIn means that it is ignored.
9108 * 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.
9110 * \param [in] arrIn arr origin array from which the extraction will be done.
9111 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9112 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9113 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9115 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9117 int seed=0,nbOfDepthPeelingPerformed=0;
9118 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9122 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9123 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9124 * 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]].
9125 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9126 * A negative value in \b arrIn means that it is ignored.
9127 * 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.
9128 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9129 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9130 * \param [in] arrIn arr origin array from which the extraction will be done.
9131 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9132 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9133 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9134 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9135 * \sa MEDCouplingUMesh::partitionBySpreadZone
9137 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9139 nbOfDepthPeelingPerformed=0;
9141 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9142 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9145 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9149 std::vector<bool> fetched(nbOfTuples,false);
9150 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9153 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)
9155 nbOfDepthPeelingPerformed=0;
9156 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9157 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9158 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9159 std::vector<bool> fetched2(nbOfTuples,false);
9161 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9163 if(*seedElt>=0 && *seedElt<nbOfTuples)
9164 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9166 { 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()); }
9168 const int *arrInPtr=arrIn->getConstPointer();
9169 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9170 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9171 std::vector<int> idsToFetch1(seedBg,seedEnd);
9172 std::vector<int> idsToFetch2;
9173 std::vector<int> *idsToFetch=&idsToFetch1;
9174 std::vector<int> *idsToFetchOther=&idsToFetch2;
9175 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9177 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9178 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9180 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9181 std::swap(idsToFetch,idsToFetchOther);
9182 idsToFetchOther->clear();
9183 nbOfDepthPeelingPerformed++;
9185 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9188 int *retPtr=ret->getPointer();
9189 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9196 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9197 * 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
9198 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9199 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9201 * \param [in] start begin of set of ids of the input extraction (included)
9202 * \param [in] end end of set of ids of the input extraction (excluded)
9203 * \param [in] step step of the set of ids in range mode.
9204 * \param [in] arrIn arr origin array from which the extraction will be done.
9205 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9206 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9207 * \param [in] srcArrIndex index array of \b srcArr
9208 * \param [out] arrOut the resulting array
9209 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9211 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9213 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9214 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9215 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9217 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9218 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9221 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9223 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9224 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9225 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9227 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9229 if(it>=0 && it<nbOfTuples)
9230 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9233 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9234 throw INTERP_KERNEL::Exception(oss.str().c_str());
9237 srcArrIndexPtr=srcArrIndex->getConstPointer();
9238 arrIo->alloc(nbOfTuples+1,1);
9239 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9240 const int *arrInPtr=arrIn->getConstPointer();
9241 const int *srcArrPtr=srcArr->getConstPointer();
9242 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9243 int *arroPtr=arro->getPointer();
9244 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9246 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9249 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9250 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9254 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9255 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9259 arrIndexOut=arrIo.retn();
9263 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9264 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9266 * \param [in] start begin of set of ids of the input extraction (included)
9267 * \param [in] end end of set of ids of the input extraction (excluded)
9268 * \param [in] step step of the set of ids in range mode.
9269 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9270 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9271 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9272 * \param [in] srcArrIndex index array of \b srcArr
9274 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9276 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9277 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9279 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9281 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9282 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9283 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9284 int *arrInOutPtr=arrInOut->getPointer();
9285 const int *srcArrPtr=srcArr->getConstPointer();
9286 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9288 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9290 if(it>=0 && it<nbOfTuples)
9292 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9293 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9296 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9297 throw INTERP_KERNEL::Exception(oss.str().c_str());
9302 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9303 throw INTERP_KERNEL::Exception(oss.str().c_str());
9309 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9310 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9311 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9312 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9313 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9315 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9317 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9319 checkFullyDefined();
9320 int mdim=getMeshDimension();
9321 int spaceDim=getSpaceDimension();
9323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9324 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9325 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9326 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9327 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9328 ret->setCoords(getCoords());
9329 ret->allocateCells((int)partition.size());
9331 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9333 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9338 cell=tmp->buildUnionOf2DMesh();
9341 cell=tmp->buildUnionOf3DMesh();
9344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9347 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9350 ret->finishInsertingCells();
9355 * This method partitions \b this into contiguous zone.
9356 * This method only needs a well defined connectivity. Coordinates are not considered here.
9357 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9359 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9362 int nbOfCellsCur=getNumberOfCells();
9363 std::vector<DataArrayInt *> ret;
9366 DataArrayInt *neigh=0,*neighI=0;
9367 computeNeighborsOfCells(neigh,neighI);
9368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9369 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9370 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9372 while(seed<nbOfCellsCur)
9374 int nbOfPeelPerformed=0;
9375 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9376 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9378 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9379 ret.push_back((*it).retn());
9383 int nbOfCellsCur=getNumberOfCells();
9384 DataArrayInt *neigh=0,*neighI=0;
9385 computeNeighborsOfCells(neigh,neighI);
9386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9388 std::vector<DataArrayInt *> ret;
9389 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9390 while(nbOfCellsCur>0)
9392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9395 ret2.push_back(tmp2); ret.push_back(tmp2);
9396 nbOfCellsCur=tmp3->getNumberOfTuples();
9399 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9400 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9404 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9407 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9414 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9415 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9417 * \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.
9418 * \return a newly allocated DataArrayInt to be managed by the caller.
9419 * \throw In case of \a code has not the right format (typically of size 3*n)
9421 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9423 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9424 std::size_t nb=code.size()/3;
9425 if(code.size()%3!=0)
9426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9427 ret->alloc((int)nb,2);
9428 int *retPtr=ret->getPointer();
9429 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9431 retPtr[0]=code[3*i+2];
9432 retPtr[1]=code[3*i+2]+code[3*i+1];
9437 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9438 _own_cell(true),_cell_id(-1),_nb_cell(0)
9443 _nb_cell=mesh->getNumberOfCells();
9447 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9455 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9456 _own_cell(false),_cell_id(bg-1),
9463 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9466 if(_cell_id<_nb_cell)
9475 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9481 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9483 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9486 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9492 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9500 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9506 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9511 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9516 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9518 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9521 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9526 _nb_cell=mesh->getNumberOfCells();
9530 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9537 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9539 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9540 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9541 if(_cell_id<_nb_cell)
9543 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9544 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9545 int startId=_cell_id;
9546 _cell_id+=nbOfElems;
9547 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9553 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9557 _conn=mesh->getNodalConnectivity()->getPointer();
9558 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9562 void MEDCouplingUMeshCell::next()
9564 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9569 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9572 std::string MEDCouplingUMeshCell::repr() const
9574 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9576 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9578 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9582 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9585 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9587 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9588 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9590 return INTERP_KERNEL::NORM_ERROR;
9593 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9596 if(_conn_lgth!=NOTICABLE_FIRST_VAL)