1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingMemArray.txx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "CellModel.hxx"
25 #include "VolSurfUser.txx"
26 #include "InterpolationUtils.hxx"
27 #include "PointLocatorAlgos.txx"
29 #include "SplitterTetra.hxx"
30 #include "DirectedBoundingBox.hxx"
31 #include "InterpKernelMeshQuality.hxx"
32 #include "InterpKernelCellSimplify.hxx"
33 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
34 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
35 #include "InterpKernelAutoPtr.hxx"
36 #include "InterpKernelGeo2DNode.hxx"
37 #include "InterpKernelGeo2DEdgeLin.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
48 using namespace ParaMEDMEM;
50 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
52 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
54 MEDCouplingUMesh *MEDCouplingUMesh::New()
56 return new MEDCouplingUMesh;
59 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
61 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
62 ret->setName(meshName);
63 ret->setMeshDimension(meshDim);
68 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
69 * between \a this and the new mesh.
70 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
71 * delete this mesh using decrRef() as it is no more needed.
73 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
79 * Returns a new MEDCouplingMesh which is a copy of \a this one.
80 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
81 * this mesh are shared by the new mesh.
82 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
83 * delete this mesh using decrRef() as it is no more needed.
85 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
87 return new MEDCouplingUMesh(*this,recDeepCpy);
90 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
94 ret+=_nodal_connec->getHeapMemorySize();
95 if(_nodal_connec_index)
96 ret+=_nodal_connec_index->getHeapMemorySize();
97 return MEDCouplingPointSet::getHeapMemorySize()+ret;
100 void MEDCouplingUMesh::updateTime() const
102 MEDCouplingPointSet::updateTime();
105 updateTimeWith(*_nodal_connec);
107 if(_nodal_connec_index)
109 updateTimeWith(*_nodal_connec_index);
113 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
118 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
119 * then \a this mesh is most probably is writable, exchangeable and available for most
120 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
121 * this method to check that all is in order with \a this mesh.
122 * \throw If the mesh dimension is not set.
123 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
124 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
125 * \throw If the connectivity data array has more than one component.
126 * \throw If the connectivity data array has a named component.
127 * \throw If the connectivity index data array has more than one component.
128 * \throw If the connectivity index data array has a named component.
130 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
133 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
135 MEDCouplingPointSet::checkCoherency();
136 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
138 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
140 std::ostringstream message;
141 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
142 throw INTERP_KERNEL::Exception(message.str().c_str());
147 if(_nodal_connec->getNumberOfComponents()!=1)
148 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
149 if(_nodal_connec->getInfoOnComponent(0)!="")
150 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
152 if(_nodal_connec_index)
154 if(_nodal_connec_index->getNumberOfComponents()!=1)
155 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
156 if(_nodal_connec_index->getInfoOnComponent(0)!="")
157 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
162 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
163 * then \a this mesh is most probably is writable, exchangeable and available for all
164 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
165 * method thoroughly checks the nodal connectivity.
166 * \param [in] eps - a not used parameter.
167 * \throw If the mesh dimension is not set.
168 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
169 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
170 * \throw If the connectivity data array has more than one component.
171 * \throw If the connectivity data array has a named component.
172 * \throw If the connectivity index data array has more than one component.
173 * \throw If the connectivity index data array has a named component.
174 * \throw If number of nodes defining an element does not correspond to the type of element.
175 * \throw If the nodal connectivity includes an invalid node id.
177 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
182 int meshDim=getMeshDimension();
183 int nbOfNodes=getNumberOfNodes();
184 int nbOfCells=getNumberOfCells();
185 const int *ptr=_nodal_connec->getConstPointer();
186 const int *ptrI=_nodal_connec_index->getConstPointer();
187 for(int i=0;i<nbOfCells;i++)
189 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
190 if((int)cm.getDimension()!=meshDim)
192 std::ostringstream oss;
193 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
194 throw INTERP_KERNEL::Exception(oss.str().c_str());
196 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
198 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
200 std::ostringstream oss;
201 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
202 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
203 throw INTERP_KERNEL::Exception(oss.str().c_str());
205 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
210 if(nodeId>=nbOfNodes)
212 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
213 throw INTERP_KERNEL::Exception(oss.str().c_str());
218 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
219 throw INTERP_KERNEL::Exception(oss.str().c_str());
223 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
225 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
226 throw INTERP_KERNEL::Exception(oss.str().c_str());
235 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
236 * then \a this mesh is most probably is writable, exchangeable and available for all
237 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
238 * \param [in] eps - a not used parameter.
239 * \throw If the mesh dimension is not set.
240 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
241 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
242 * \throw If the connectivity data array has more than one component.
243 * \throw If the connectivity data array has a named component.
244 * \throw If the connectivity index data array has more than one component.
245 * \throw If the connectivity index data array has a named component.
246 * \throw If number of nodes defining an element does not correspond to the type of element.
247 * \throw If the nodal connectivity includes an invalid node id.
249 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
251 checkCoherency1(eps);
255 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
256 * elements contained in the mesh. For more info on the mesh dimension see
257 * \ref MEDCouplingUMeshPage.
258 * \param [in] meshDim - a new mesh dimension.
259 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
261 void MEDCouplingUMesh::setMeshDimension(int meshDim)
263 if(meshDim<-1 || meshDim>3)
264 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
270 * Allocates memory to store given number of cells.
271 * \param [in] nbOfCells - number of cell \a this mesh will contain.
273 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
274 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
276 void MEDCouplingUMesh::allocateCells(int nbOfCells)
278 if(_nodal_connec_index)
280 _nodal_connec_index->decrRef();
284 _nodal_connec->decrRef();
286 _nodal_connec_index=DataArrayInt::New();
287 _nodal_connec_index->reserve(nbOfCells+1);
288 _nodal_connec_index->pushBackSilent(0);
289 _nodal_connec=DataArrayInt::New();
290 _nodal_connec->reserve(2*nbOfCells);
296 * Appends a cell to the connectivity array. For deeper understanding what is
297 * happening see \ref MEDCouplingUMeshNodalConnectivity.
298 * \param [in] type - type of cell to add.
299 * \param [in] size - number of nodes constituting this cell.
300 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
302 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
303 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
305 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
307 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
308 if(_nodal_connec_index==0)
309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
310 if((int)cm.getDimension()==_mesh_dim)
313 if(size!=(int)cm.getNumberOfNodes())
315 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
316 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
317 throw INTERP_KERNEL::Exception(oss.str().c_str());
319 int idx=_nodal_connec_index->back();
321 _nodal_connec_index->pushBackSilent(val);
322 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
327 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
328 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
329 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
330 throw INTERP_KERNEL::Exception(oss.str().c_str());
335 * Compacts data arrays to release unused memory. This method is to be called after
336 * finishing cell insertion using \a this->insertNextCell().
338 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
339 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
341 void MEDCouplingUMesh::finishInsertingCells()
343 _nodal_connec->pack();
344 _nodal_connec_index->pack();
345 _nodal_connec->declareAsNew();
346 _nodal_connec_index->declareAsNew();
351 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
352 * Useful for python users.
354 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
356 return new MEDCouplingUMeshCellIterator(this);
360 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
361 * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
362 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
363 * Useful for python users.
365 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
367 if(!checkConsecutiveCellTypes())
368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
369 return new MEDCouplingUMeshCellByTypeEntry(this);
373 * Returns a set of all cell types available in \a this mesh.
374 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
376 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
382 * This method is a method that compares 'this' and 'other'.
383 * This method compares \b all attributes, even names and component names.
385 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
388 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
389 std::ostringstream oss; oss.precision(15);
390 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
393 reason="mesh given in input is not castable in MEDCouplingUMesh !";
396 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
398 if(_mesh_dim!=otherC->_mesh_dim)
400 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
404 if(_types!=otherC->_types)
406 oss << "umesh geometric type mismatch :\nThis geometric types are :";
407 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
408 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
409 oss << "\nOther geometric types are :";
410 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
411 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
415 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
416 if(_nodal_connec==0 || otherC->_nodal_connec==0)
418 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
421 if(_nodal_connec!=otherC->_nodal_connec)
422 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
424 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
427 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
428 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
430 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
433 if(_nodal_connec_index!=otherC->_nodal_connec_index)
434 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
436 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
443 * \brief Checks if data arrays of this mesh (node coordinates, nodal
444 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
446 * \param [in] other - the mesh to compare with.
447 * \param [in] prec - precision value used to compare node coordinates.
448 * \return bool - \a true if the two meshes are same.
450 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
452 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
455 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
457 if(_mesh_dim!=otherC->_mesh_dim)
459 if(_types!=otherC->_types)
461 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
462 if(_nodal_connec==0 || otherC->_nodal_connec==0)
464 if(_nodal_connec!=otherC->_nodal_connec)
465 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
467 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
468 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
470 if(_nodal_connec_index!=otherC->_nodal_connec_index)
471 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
477 * Checks if \a this and \a other meshes are geometrically equivalent, else an
478 * exception is thrown. The meshes are
479 * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
480 * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
481 * the \a other mesh (with use of a specified cell comparison technique). The mapping
482 * from \a other to \a this for nodes and cells is returned via out parameters.
483 * \param [in] other - the mesh to compare with.
484 * \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
485 * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
486 * \param [in] prec - the precision used to compare nodes of the two meshes.
487 * \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
488 * to delete this array using decrRef() as it is no more needed.
489 * \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
490 * to delete this array using decrRef() as it is no more needed.
491 * \throw If the two meshes do not match.
493 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
494 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
496 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
497 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
499 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
501 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
502 MEDCouplingMesh::checkFastEquivalWith(other,prec);
503 if(_types!=otherC->_types)
504 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
505 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
508 int oldNbOfNodes=getNumberOfNodes();
509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
512 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
513 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
514 if(pt!=da->getConstPointer()+da->getNbOfElems())
515 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
516 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
519 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
522 da=m->zipConnectivityTraducer(cellCompPol);
523 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
524 pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
525 if(pt!=da->getConstPointer()+da->getNbOfElems())
526 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
527 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
528 nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
529 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
533 * Checks if \a this and \a other meshes are geometrically equivalent, else an
534 * exception is thrown. The meshes are considered equivalent if (1) they share one
535 * node coordinates array and (2) they contain the same cells (with use of a specified
536 * cell comparison technique). The mapping from cells of the \a other to ones of \a this
537 * is returned via an out parameter.
538 * \param [in] other - the mesh to compare with.
539 * \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
540 * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
541 * \param [in] prec - a not used parameter.
542 * \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
543 * to delete this array using decrRef() as it is no more needed.
544 * \throw If the two meshes do not match.
546 * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
547 * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
549 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
550 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
552 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
554 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
555 MEDCouplingMesh::checkFastEquivalWith(other,prec);
556 if(_types!=otherC->_types)
557 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
558 if(_coords!=otherC->_coords)
559 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
560 std::vector<const MEDCouplingUMesh *> ms(2);
563 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
565 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
566 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
567 if(pt!=da->getConstPointer()+da->getNbOfElems())
569 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
571 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
572 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
576 * Checks if \a this and \a other meshes are geometrically equivalent with high
577 * probability, else an exception is thrown. The meshes are considered equivalent if
578 * (1) meshes contain the same number of nodes and the same number of elements of the
579 * same types (2) three cells of the two meshes are based on coincident nodes (with a
580 * specified precision).
581 * \param [in] other - the mesh to compare with.
582 * \param [in] prec - the precision used to compare nodes of the two meshes.
583 * \throw If the two meshes do not match.
585 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
587 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
589 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
590 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
591 int nbOfCells=getNumberOfCells();
595 status&=areCellsFrom2MeshEqual(otherC,0,prec);
596 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
597 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
599 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
603 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
604 * cells each node belongs to.
605 * \warning For speed reasons, this method does not check if node ids in the nodal
606 * connectivity correspond to the size of node coordinates array.
607 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
608 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
609 * dividing cell ids in \a revNodal into groups each referring to one
610 * node. Its every element (except the last one) is an index pointing to the
611 * first id of a group of cells. For example cells sharing the node #1 are
612 * described by following range of indices:
613 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
614 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
615 * Number of cells sharing the *i*-th node is
616 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
617 * \throw If the coordinates array is not set.
618 * \throw If the nodal connectivity of cells is not defined.
620 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
621 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
623 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
626 int nbOfNodes=getNumberOfNodes();
627 int *revNodalIndxPtr=new int[nbOfNodes+1];
628 revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
629 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
630 const int *conn=_nodal_connec->getConstPointer();
631 const int *connIndex=_nodal_connec_index->getConstPointer();
632 int nbOfCells=getNumberOfCells();
633 int nbOfEltsInRevNodal=0;
634 for(int eltId=0;eltId<nbOfCells;eltId++)
636 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
637 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
638 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
639 if(*iter>=0)//for polyhedrons
641 nbOfEltsInRevNodal++;
642 revNodalIndxPtr[(*iter)+1]++;
645 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
646 int *revNodalPtr=new int[nbOfEltsInRevNodal];
647 revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
648 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
649 for(int eltId=0;eltId<nbOfCells;eltId++)
651 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
652 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
653 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
654 if(*iter>=0)//for polyhedrons
655 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
661 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
666 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
672 if(cm.getOrientationStatus(nb,conn1,conn2))
679 class MinusOneSonsGenerator
682 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
683 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
684 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
685 static const int DELTA=1;
687 const INTERP_KERNEL::CellModel& _cm;
690 class MinusOneSonsGeneratorBiQuadratic
693 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
694 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
695 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
696 static const int DELTA=1;
698 const INTERP_KERNEL::CellModel& _cm;
701 class MinusTwoSonsGenerator
704 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
705 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
706 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
707 static const int DELTA=2;
709 const INTERP_KERNEL::CellModel& _cm;
715 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
716 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
717 * describing correspondence between cells of \a this and the result meshes are
718 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
719 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
720 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
721 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
722 * \warning For speed reasons, this method does not check if node ids in the nodal
723 * connectivity correspond to the size of node coordinates array.
724 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
725 * to write this mesh to the MED file, its cells must be sorted using
726 * sortCellsInMEDFileFrmt().
727 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
728 * each cell of \a this mesh.
729 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
730 * dividing cell ids in \a desc into groups each referring to one
731 * cell of \a this mesh. Its every element (except the last one) is an index
732 * pointing to the first id of a group of cells. For example cells of the
733 * result mesh bounding the cell #1 of \a this mesh are described by following
735 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
736 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
737 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
738 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
739 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
740 * by each cell of the result mesh.
741 * \param [in,out] revDescIndx - the array, of length one more than number of cells
742 * in the result mesh,
743 * dividing cell ids in \a revDesc into groups each referring to one
744 * cell of the result mesh the same way as \a descIndx divides \a desc.
745 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
746 * delete this mesh using decrRef() as it is no more needed.
747 * \throw If the coordinates array is not set.
748 * \throw If the nodal connectivity of cells is node defined.
749 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
750 * revDescIndx == NULL.
752 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
753 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
754 * \sa buildDescendingConnectivity2()
756 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
758 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
762 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
763 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
764 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
765 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
766 * \sa MEDCouplingUMesh::buildDescendingConnectivity
768 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
771 if(getMeshDimension()!=3)
772 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
773 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
777 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
778 * this->getMeshDimension(), that bound cells of \a this mesh. In
779 * addition arrays describing correspondence between cells of \a this and the result
780 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
781 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
782 * mesh. This method differs from buildDescendingConnectivity() in that apart
783 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
784 * result meshes. So a positive id means that order of nodes in corresponding cells
785 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
786 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
787 * i.e. cell ids are one-based.
788 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
789 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
790 * \warning For speed reasons, this method does not check if node ids in the nodal
791 * connectivity correspond to the size of node coordinates array.
792 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
793 * to write this mesh to the MED file, its cells must be sorted using
794 * sortCellsInMEDFileFrmt().
795 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
796 * each cell of \a this mesh.
797 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
798 * dividing cell ids in \a desc into groups each referring to one
799 * cell of \a this mesh. Its every element (except the last one) is an index
800 * pointing to the first id of a group of cells. For example cells of the
801 * result mesh bounding the cell #1 of \a this mesh are described by following
803 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
804 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
805 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
806 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
807 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
808 * by each cell of the result mesh.
809 * \param [in,out] revDescIndx - the array, of length one more than number of cells
810 * in the result mesh,
811 * dividing cell ids in \a revDesc into groups each referring to one
812 * cell of the result mesh the same way as \a descIndx divides \a desc.
813 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
814 * shares the node coordinates array with \a this mesh. The caller is to
815 * delete this mesh using decrRef() as it is no more needed.
816 * \throw If the coordinates array is not set.
817 * \throw If the nodal connectivity of cells is node defined.
818 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
819 * revDescIndx == NULL.
821 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
822 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
823 * \sa buildDescendingConnectivity()
825 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
827 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
831 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
832 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
833 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
834 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836 * \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
837 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
838 * \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.
840 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
846 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
848 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
852 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
853 * 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,
854 * excluding a set of meshdim-1 cells in input descending connectivity.
855 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
856 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
857 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
859 * \param [in] desc descending connectivity array.
860 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
861 * \param [in] revDesc reverse descending connectivity array.
862 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
863 * \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
864 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
865 * \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.
867 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
868 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
870 if(!desc || !descIndx || !revDesc || !revDescIndx)
871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
872 const int *descPtr=desc->getConstPointer();
873 const int *descIPtr=descIndx->getConstPointer();
874 const int *revDescPtr=revDesc->getConstPointer();
875 const int *revDescIPtr=revDescIndx->getConstPointer();
877 int nbCells=descIndx->getNumberOfTuples()-1;
878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
880 int *out1Ptr=out1->getPointer();
882 out0->reserve(desc->getNumberOfTuples());
883 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
885 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
887 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
889 out0->insertAtTheEnd(s.begin(),s.end());
891 *out1Ptr=out0->getNumberOfTuples();
893 neighbors=out0.retn();
894 neighborsIndx=out1.retn();
900 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
901 * For speed reasons no check of this will be done.
903 template<class SonsGenerator>
904 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
906 if(!desc || !descIndx || !revDesc || !revDescIndx)
907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
908 checkConnectivityFullyDefined();
909 int nbOfCells=getNumberOfCells();
910 int nbOfNodes=getNumberOfNodes();
911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
912 int *revNodalIndxPtr=revNodalIndx->getPointer();
913 const int *conn=_nodal_connec->getConstPointer();
914 const int *connIndex=_nodal_connec_index->getConstPointer();
915 std::string name="Mesh constituent of "; name+=getName();
916 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
917 ret->setCoords(getCoords());
918 ret->allocateCells(2*nbOfCells);
919 descIndx->alloc(nbOfCells+1,1);
920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
921 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
922 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
924 int pos=connIndex[eltId];
925 int posP1=connIndex[eltId+1];
926 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
927 SonsGenerator sg(cm);
928 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
929 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
930 for(unsigned i=0;i<nbOfSons;i++)
932 INTERP_KERNEL::NormalizedCellType cmsId;
933 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
934 for(unsigned k=0;k<nbOfNodesSon;k++)
936 revNodalIndxPtr[tmp[k]+1]++;
937 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
938 revDesc2->pushBackSilent(eltId);
940 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
942 int nbOfCellsM1=ret->getNumberOfCells();
943 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
944 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
945 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
946 int *revNodalPtr=revNodal->getPointer();
947 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
948 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
949 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
951 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
952 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
953 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
954 if(*iter>=0)//for polyhedrons
955 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
958 DataArrayInt *commonCells=0,*commonCellsI=0;
959 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
961 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
962 int newNbOfCellsM1=-1;
963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
964 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
965 std::vector<bool> isImpacted(nbOfCellsM1,false);
966 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
967 for(int work2=work[0];work2!=work[1];work2++)
968 isImpacted[commonCellsPtr[work2]]=true;
969 const int *o2nM1Ptr=o2nM1->getConstPointer();
970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
971 const int *n2oM1Ptr=n2oM1->getConstPointer();
972 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
973 ret2->copyTinyInfoFrom(this);
974 desc->alloc(descIndx->back(),1);
975 int *descPtr=desc->getPointer();
976 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
977 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
980 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
983 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
985 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
986 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
989 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
992 revDesc->reserve(newNbOfCellsM1);
993 revDescIndx->alloc(newNbOfCellsM1+1,1);
994 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
995 const int *revDesc2Ptr=revDesc2->getConstPointer();
996 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
998 int oldCellIdM1=n2oM1Ptr[i];
999 if(!isImpacted[oldCellIdM1])
1001 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1002 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1006 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1007 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1008 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1016 struct MEDCouplingAccVisit
1018 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1019 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1020 int _new_nb_of_nodes;
1026 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1027 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1028 * array of cell ids. Pay attention that after conversion all algorithms work slower
1029 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1030 * conversion due presence of invalid ids in the array of cells to convert, as a
1031 * result \a this mesh contains some already converted elements. In this case the 2D
1032 * mesh remains valid but 3D mesh becomes \b inconsistent!
1033 * \warning This method can significantly modify the order of geometric types in \a this,
1034 * hence, to write this mesh to the MED file, its cells must be sorted using
1035 * sortCellsInMEDFileFrmt().
1036 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1037 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1038 * cellIdsToConvertBg.
1039 * \throw If the coordinates array is not set.
1040 * \throw If the nodal connectivity of cells is node defined.
1041 * \throw If dimension of \a this mesh is not either 2 or 3.
1043 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1044 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1046 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1048 checkFullyDefined();
1049 int dim=getMeshDimension();
1051 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1052 int nbOfCells=getNumberOfCells();
1055 const int *connIndex=_nodal_connec_index->getConstPointer();
1056 int *conn=_nodal_connec->getPointer();
1057 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1059 if(*iter>=0 && *iter<nbOfCells)
1061 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1063 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1065 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1069 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1070 oss << " in range [0," << nbOfCells << ") !";
1071 throw INTERP_KERNEL::Exception(oss.str().c_str());
1077 int *connIndex=_nodal_connec_index->getPointer();
1078 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1079 const int *connOld=_nodal_connec->getConstPointer();
1080 int connOldLgth=_nodal_connec->getNbOfElems();
1081 std::vector<int> connNew(connOld,connOld+connOldLgth);
1082 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1084 if(*iter>=0 && *iter<nbOfCells)
1086 int pos=connIndex[*iter];
1087 int posP1=connIndex[(*iter)+1];
1088 int lgthOld=posP1-pos-1;
1089 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1090 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1091 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1092 int *tmp=new int[nbOfFaces*lgthOld];
1094 for(int j=0;j<(int)nbOfFaces;j++)
1096 INTERP_KERNEL::NormalizedCellType type;
1097 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1101 std::size_t newLgth=std::distance(tmp,work)-1;
1102 std::size_t delta=newLgth-lgthOld;
1103 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1104 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1105 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1110 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1111 oss << " in range [0," << nbOfCells << ") !";
1112 throw INTERP_KERNEL::Exception(oss.str().c_str());
1115 _nodal_connec->alloc((int)connNew.size(),1);
1116 int *newConnPtr=_nodal_connec->getPointer();
1117 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1123 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1124 * polyhedrons (if \a this is a 3D mesh).
1125 * \warning As this method is purely for user-friendliness and no optimization is
1126 * done to avoid construction of a useless vector, this method can be costly
1128 * \throw If the coordinates array is not set.
1129 * \throw If the nodal connectivity of cells is node defined.
1130 * \throw If dimension of \a this mesh is not either 2 or 3.
1132 void MEDCouplingUMesh::convertAllToPoly()
1134 int nbOfCells=getNumberOfCells();
1135 std::vector<int> cellIds(nbOfCells);
1136 for(int i=0;i<nbOfCells;i++)
1138 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1142 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1143 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1144 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1145 * base facet of the volume and the second half of nodes describes an opposite facet
1146 * having the same number of nodes as the base one. This method converts such
1147 * connectivity to a valid polyhedral format where connectivity of each facet is
1148 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1149 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1150 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1151 * a correct orientation of the first facet of a polyhedron, else orientation of a
1152 * corrected cell is reverse.<br>
1153 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1154 * it releases the user from boring description of polyhedra connectivity in the valid
1156 * \throw If \a this->getMeshDimension() != 3.
1157 * \throw If \a this->getSpaceDimension() != 3.
1158 * \throw If the nodal connectivity of cells is not defined.
1159 * \throw If the coordinates array is not set.
1160 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1161 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1163 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1164 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1166 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1168 checkFullyDefined();
1169 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1170 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1171 int nbOfCells=getNumberOfCells();
1172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1173 newCi->alloc(nbOfCells+1,1);
1174 int *newci=newCi->getPointer();
1175 const int *ci=_nodal_connec_index->getConstPointer();
1176 const int *c=_nodal_connec->getConstPointer();
1178 for(int i=0;i<nbOfCells;i++)
1180 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1181 if(type==INTERP_KERNEL::NORM_POLYHED)
1183 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1185 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1186 throw INTERP_KERNEL::Exception(oss.str().c_str());
1188 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1191 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 !";
1192 throw INTERP_KERNEL::Exception(oss.str().c_str());
1195 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)
1198 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1201 newC->alloc(newci[nbOfCells],1);
1202 int *newc=newC->getPointer();
1203 for(int i=0;i<nbOfCells;i++)
1205 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1206 if(type==INTERP_KERNEL::NORM_POLYHED)
1208 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1209 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1211 for(std::size_t j=0;j<n1;j++)
1213 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1215 newc[n1+5*j+1]=c[ci[i]+1+j];
1216 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1217 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1218 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1223 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1225 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1226 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1231 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1232 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1233 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1234 * to write this mesh to the MED file, its cells must be sorted using
1235 * sortCellsInMEDFileFrmt().
1236 * \return \c true if at least one cell has been converted, \c false else. In the
1237 * last case the nodal connectivity remains unchanged.
1238 * \throw If the coordinates array is not set.
1239 * \throw If the nodal connectivity of cells is not defined.
1240 * \throw If \a this->getMeshDimension() < 0.
1242 bool MEDCouplingUMesh::unPolyze()
1244 checkFullyDefined();
1245 int mdim=getMeshDimension();
1247 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1250 int nbOfCells=getNumberOfCells();
1253 int initMeshLgth=getMeshLength();
1254 int *conn=_nodal_connec->getPointer();
1255 int *index=_nodal_connec_index->getPointer();
1260 for(int i=0;i<nbOfCells;i++)
1262 lgthOfCurCell=index[i+1]-posOfCurCell;
1263 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1264 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1265 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1269 switch(cm.getDimension())
1273 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1274 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1275 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1280 int nbOfFaces,lgthOfPolyhConn;
1281 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1282 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1287 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1291 ret=ret || (newType!=type);
1292 conn[newPos]=newType;
1294 posOfCurCell=index[i+1];
1299 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1300 newPos+=lgthOfCurCell;
1301 posOfCurCell+=lgthOfCurCell;
1305 if(newPos!=initMeshLgth)
1306 _nodal_connec->reAlloc(newPos);
1313 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1314 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1315 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1317 * \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
1320 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1322 checkFullyDefined();
1323 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1324 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1325 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1326 coords->recenterForMaxPrecision(eps);
1328 int nbOfCells=getNumberOfCells();
1329 const int *conn=_nodal_connec->getConstPointer();
1330 const int *index=_nodal_connec_index->getConstPointer();
1331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1332 connINew->alloc(nbOfCells+1,1);
1333 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1336 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1338 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1340 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1344 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1345 *connINewPtr=connNew->getNumberOfTuples();
1348 setConnectivity(connNew,connINew,false);
1352 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1353 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1354 * the format of returned DataArrayInt instance.
1356 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1357 * \sa MEDCouplingUMesh::getNodeIdsInUse
1359 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1361 checkConnectivityFullyDefined();
1362 int nbOfCells=getNumberOfCells();
1363 const int *connIndex=_nodal_connec_index->getConstPointer();
1364 const int *conn=_nodal_connec->getConstPointer();
1365 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1366 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1367 std::vector<bool> retS(maxElt,false);
1368 for(int i=0;i<nbOfCells;i++)
1369 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1373 for(int i=0;i<maxElt;i++)
1376 DataArrayInt *ret=DataArrayInt::New();
1378 int *retPtr=ret->getPointer();
1379 for(int i=0;i<maxElt;i++)
1386 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1387 * \sa MEDCouplingUMesh::getNodeIdsInUse
1389 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1391 int nbOfNodes=(int)nodeIdsInUse.size();
1392 int nbOfCells=getNumberOfCells();
1393 const int *connIndex=_nodal_connec_index->getConstPointer();
1394 const int *conn=_nodal_connec->getConstPointer();
1395 for(int i=0;i<nbOfCells;i++)
1396 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1399 if(conn[j]<nbOfNodes)
1400 nodeIdsInUse[conn[j]]=true;
1403 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1404 throw INTERP_KERNEL::Exception(oss.str().c_str());
1410 * Finds nodes not used in any cell and returns an array giving a new id to every node
1411 * by excluding the unused nodes, for which the array holds -1. The result array is
1412 * a mapping in "Old to New" mode.
1413 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1414 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1415 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1416 * if the node is unused or a new id else. The caller is to delete this
1417 * array using decrRef() as it is no more needed.
1418 * \throw If the coordinates array is not set.
1419 * \throw If the nodal connectivity of cells is not defined.
1420 * \throw If the nodal connectivity includes an invalid id.
1422 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1423 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1424 * \sa computeNodeIdsAlg()
1426 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1429 int nbOfNodes=getNumberOfNodes();
1430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1431 ret->alloc(nbOfNodes,1);
1432 int *traducer=ret->getPointer();
1433 std::fill(traducer,traducer+nbOfNodes,-1);
1434 int nbOfCells=getNumberOfCells();
1435 const int *connIndex=_nodal_connec_index->getConstPointer();
1436 const int *conn=_nodal_connec->getConstPointer();
1437 for(int i=0;i<nbOfCells;i++)
1438 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1441 if(conn[j]<nbOfNodes)
1442 traducer[conn[j]]=1;
1445 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1446 throw INTERP_KERNEL::Exception(oss.str().c_str());
1449 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1450 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1455 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1456 * For each cell in \b this the number of nodes constituting cell is computed.
1457 * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1458 * For polyhedrons, the face separation (-1) are excluded from the couting.
1460 * \return a newly allocated array
1462 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1464 checkConnectivityFullyDefined();
1465 int nbOfCells=getNumberOfCells();
1466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1467 ret->alloc(nbOfCells,1);
1468 int *retPtr=ret->getPointer();
1469 const int *conn=getNodalConnectivity()->getConstPointer();
1470 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1471 for(int i=0;i<nbOfCells;i++,retPtr++)
1473 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1474 *retPtr=connI[i+1]-connI[i]-1;
1476 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1482 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1483 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1484 * array mean that the corresponding old node is no more used.
1485 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1486 * this->getNumberOfNodes() before call of this method. The caller is to
1487 * delete this array using decrRef() as it is no more needed.
1488 * \throw If the coordinates array is not set.
1489 * \throw If the nodal connectivity of cells is not defined.
1490 * \throw If the nodal connectivity includes an invalid id.
1492 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1493 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1495 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1497 int newNbOfNodes=-1;
1498 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1499 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1504 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1505 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1507 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1512 return AreCellsEqual0(conn,connI,cell1,cell2);
1514 return AreCellsEqual1(conn,connI,cell1,cell2);
1516 return AreCellsEqual2(conn,connI,cell1,cell2);
1518 return AreCellsEqual3(conn,connI,cell1,cell2);
1520 return AreCellsEqual7(conn,connI,cell1,cell2);
1522 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1526 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1528 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1530 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1531 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1536 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1538 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1540 int sz=connI[cell1+1]-connI[cell1];
1541 if(sz==connI[cell2+1]-connI[cell2])
1543 if(conn[connI[cell1]]==conn[connI[cell2]])
1545 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1546 unsigned dim=cm.getDimension();
1552 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1553 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1554 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1555 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1556 return work!=tmp+sz1?1:0;
1559 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1562 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1569 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1571 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1573 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1575 if(conn[connI[cell1]]==conn[connI[cell2]])
1577 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1578 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1586 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1588 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1590 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1592 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1593 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1600 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1602 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1604 int sz=connI[cell1+1]-connI[cell1];
1605 if(sz==connI[cell2+1]-connI[cell2])
1607 if(conn[connI[cell1]]==conn[connI[cell2]])
1609 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1610 unsigned dim=cm.getDimension();
1616 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1617 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1618 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1619 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1624 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1625 std::reverse_iterator<int *> it2((int *)tmp);
1626 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1632 return work!=tmp+sz1?1:0;
1635 {//case of SEG2 and SEG3
1636 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1638 if(!cm.isQuadratic())
1640 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1641 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1642 if(std::equal(it1,it2,conn+connI[cell2]+1))
1648 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])
1655 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1663 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1664 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1666 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1668 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1670 std::vector<int> c1,c2;
1671 getNodeIdsOfCell(cellId,c1);
1672 other->getNodeIdsOfCell(cellId,c2);
1673 std::size_t sz=c1.size();
1676 for(std::size_t i=0;i<sz;i++)
1678 std::vector<double> n1,n2;
1679 getCoordinatesOfNode(c1[0],n1);
1680 other->getCoordinatesOfNode(c2[0],n2);
1681 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1682 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1683 if(*std::max_element(n1.begin(),n1.end())>prec)
1690 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1691 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1692 * and result remains unchanged.
1693 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1694 * If in 'candidates' pool -1 value is considered as an empty value.
1695 * WARNING this method returns only ONE set of result !
1697 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1699 if(candidates.size()<1)
1702 std::vector<int>::const_iterator iter=candidates.begin();
1703 int start=(*iter++);
1704 for(;iter!=candidates.end();iter++)
1706 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1711 result->pushBackSilent(start);
1715 result->pushBackSilent(*iter);
1717 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1724 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1725 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1727 * \param [in] compType input specifying the technique used to compare cells each other.
1728 * - 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.
1729 * - 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)
1730 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1731 * - 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
1732 * can be used for users not sensitive to orientation of cell
1733 * \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.
1734 * \param [out] commonCells
1735 * \param [out] commonCellsI
1736 * \return the correspondance array old to new in a newly allocated array.
1739 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1741 checkConnectivityFullyDefined();
1742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1743 getReverseNodalConnectivity(revNodal,revNodalI);
1744 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1747 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1748 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1751 int nbOfCells=nodalI->getNumberOfTuples()-1;
1752 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1753 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1754 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1755 std::vector<bool> isFetched(nbOfCells,false);
1758 for(int i=0;i<nbOfCells;i++)
1762 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1763 std::vector<int> v,v2;
1764 if(connOfNode!=connPtr+connIPtr[i+1])
1766 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1767 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1770 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1774 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1775 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1776 v2.resize(std::distance(v2.begin(),it));
1780 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1782 int pos=commonCellsI->back();
1783 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1784 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1785 isFetched[*it]=true;
1793 for(int i=startCellId;i<nbOfCells;i++)
1797 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1798 std::vector<int> v,v2;
1799 if(connOfNode!=connPtr+connIPtr[i+1])
1801 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1804 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1808 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1809 v2.resize(std::distance(v2.begin(),it));
1813 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1815 int pos=commonCellsI->back();
1816 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1817 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1818 isFetched[*it]=true;
1824 commonCellsArr=commonCells.retn();
1825 commonCellsIArr=commonCellsI.retn();
1829 * Removes duplicates of cells from \a this mesh and returns an array mapping between
1830 * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1831 * equal cells found.
1832 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1833 * to write this mesh to the MED file, its cells must be sorted using
1834 * sortCellsInMEDFileFrmt().
1835 * \param [in] compType - specifies a cell comparison technique. Meaning of its
1836 * valid values [0,1,2] is as follows.
1837 * - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1838 * connectivity and type. This is the strongest policy.
1839 * - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1840 * are based on same nodes and have the same type and orientation.
1841 * - 2 : "nodal". Two cells are considered equal \c iff they
1842 * are based on same nodes and have the same type. This is the weakest
1843 * policy, it can be used by users not sensitive to cell orientation.
1844 * \param [in] startCellId - specifies the cell id at which search for equal cells
1845 * starts. By default it is 0, which means that all cells in \a this will be
1847 * \return DataArrayInt - a new instance of DataArrayInt, of length \a
1848 * this->getNumberOfCells() before call of this method. The caller is to
1849 * delete this array using decrRef() as it is no more needed.
1850 * \throw If the coordinates array is not set.
1851 * \throw If the nodal connectivity of cells is not defined.
1852 * \throw If the nodal connectivity includes an invalid id.
1854 * \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1855 * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1857 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1859 DataArrayInt *commonCells=0,*commonCellsI=0;
1860 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1862 int newNbOfCells=-1;
1863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1864 commonCellsI->end(),newNbOfCells);
1865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1866 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1867 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1872 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1873 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1874 * than \a other->getNumberOfCells() in the returned array means that there is no
1875 * corresponding cell in \a this mesh.
1876 * It is expected that \a this and \a other meshes share the same node coordinates
1877 * array, if it is not so an exception is thrown.
1878 * \param [in] other - the mesh to compare with.
1879 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1880 * valid values [0,1,2], see zipConnectivityTraducer().
1881 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1882 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1883 * values. The caller is to delete this array using
1884 * decrRef() as it is no more needed.
1885 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1888 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1889 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1890 * \sa checkDeepEquivalOnSameNodesWith()
1891 * \sa checkGeoEquivalWith()
1893 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1895 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1896 int nbOfCells=getNumberOfCells();
1897 static const int possibleCompType[]={0,1,2};
1898 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1900 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1901 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1903 throw INTERP_KERNEL::Exception(oss.str().c_str());
1905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1906 arr=o2n->substr(nbOfCells);
1907 arr->setName(other->getName());
1909 if(other->getNumberOfCells()==0)
1911 return arr->getMaxValue(tmp)<nbOfCells;
1915 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1916 * This method tries to determine if \b other is fully included in \b this.
1917 * The main difference is that this method is not expected to throw exception.
1918 * This method has two outputs :
1920 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1921 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1923 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1925 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1926 DataArrayInt *commonCells=0,*commonCellsI=0;
1927 int thisNbCells=getNumberOfCells();
1928 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1930 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1931 int otherNbCells=other->getNumberOfCells();
1932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1933 arr2->alloc(otherNbCells,1);
1934 arr2->fillWithZero();
1935 int *arr2Ptr=arr2->getPointer();
1936 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1937 for(int i=0;i<nbOfCommon;i++)
1939 int start=commonCellsPtr[commonCellsIPtr[i]];
1940 if(start<thisNbCells)
1942 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1944 int sig=commonCellsPtr[j]>0?1:-1;
1945 int val=std::abs(commonCellsPtr[j])-1;
1946 if(val>=thisNbCells)
1947 arr2Ptr[val-thisNbCells]=sig*(start+1);
1951 arr2->setName(other->getName());
1952 if(arr2->presenceOfValue(0))
1959 * Merges nodes equal within \a precision and returns an array describing the
1960 * permutation used to remove duplicate nodes.
1961 * \param [in] precision - minimal absolute distance between two nodes at which they are
1962 * considered not coincident.
1963 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1964 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1965 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1966 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1967 * is to delete this array using decrRef() as it is no more needed.
1968 * \throw If the coordinates array is not set.
1969 * \throw If the nodal connectivity of cells is not defined.
1971 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1972 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1974 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1976 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1978 renumberNodes(ret->getConstPointer(),newNbOfNodes);
1984 * Merges nodes equal within \a precision and returns an array describing the
1985 * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1986 * of merged nodes is changed to be at their barycenter.
1987 * \param [in] precision - minimal absolute distance between two nodes at which they are
1988 * considered not coincident.
1989 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1990 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1991 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1992 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1993 * is to delete this array using decrRef() as it is no more needed.
1994 * \throw If the coordinates array is not set.
1995 * \throw If the nodal connectivity of cells is not defined.
1997 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1998 * \ref py_mcumesh_mergeNodes "Here is a Python example".
2000 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
2002 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2004 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
2009 * Substitutes node coordinates array of \a this mesh with that of \a other mesh
2010 * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
2011 * meshes match with a specified precision, else an exception is thrown and \a this
2012 * remains unchanged. In case of success the nodal connectivity of \a this mesh
2013 * is permuted according to new order of nodes.
2014 * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
2015 * coordinates (and so more expensive) than simple equality.
2016 * \param [in] other - the other mesh whose node coordinates array will be used by
2017 * \a this mesh in case of their equality.
2018 * \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
2019 * \throw If the coordinates array of \a this is not set.
2020 * \throw If the coordinates array of \a other is not set.
2021 * \throw If the coordinates of \a this and \a other do not match.
2023 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
2025 const DataArrayDouble *coords=other.getCoords();
2027 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
2029 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
2030 int otherNbOfNodes=other.getNumberOfNodes();
2031 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
2033 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
2034 setCoords(newCoords);
2035 bool areNodesMerged;
2037 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
2040 setCoords(oldCoords);
2041 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
2043 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
2044 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
2045 if(pt!=da->getConstPointer()+da->getNbOfElems())
2047 setCoords(oldCoords);
2048 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
2050 setCoords(oldCoords);
2051 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
2056 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2057 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2058 * cellIds is not given explicitely but by a range python like.
2060 * \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.
2061 * \return a newly allocated
2063 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2064 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2066 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
2068 if(getMeshDimension()!=-1)
2070 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
2077 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2079 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2081 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2083 return const_cast<MEDCouplingUMesh *>(this);
2088 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2089 * The result mesh shares or not the node coordinates array with \a this mesh depending
2090 * on \a keepCoords parameter.
2091 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2092 * to write this mesh to the MED file, its cells must be sorted using
2093 * sortCellsInMEDFileFrmt().
2094 * \param [in] begin - an array of cell ids to include to the new mesh.
2095 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2096 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2097 * array of \a this mesh, else "free" nodes are removed from the result mesh
2098 * by calling zipCoords().
2099 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2100 * to delete this mesh using decrRef() as it is no more needed.
2101 * \throw If the coordinates array is not set.
2102 * \throw If the nodal connectivity of cells is not defined.
2103 * \throw If any cell id in the array \a begin is not valid.
2105 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2106 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2108 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2110 if(getMeshDimension()!=-1)
2112 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
2120 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2122 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2124 return const_cast<MEDCouplingUMesh *>(this);
2129 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2131 * 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.
2132 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2133 * The number of cells of \b this will remain the same with this method.
2135 * \param [in] begin begin of cell ids (included) of cells in this to assign
2136 * \param [in] end end of cell ids (excluded) of cells in this to assign
2137 * \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).
2138 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2140 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2142 checkConnectivityFullyDefined();
2143 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2144 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2145 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2146 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2148 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2149 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2150 throw INTERP_KERNEL::Exception(oss.str().c_str());
2152 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2153 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2155 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2156 throw INTERP_KERNEL::Exception(oss.str().c_str());
2158 int nbOfCells=getNumberOfCells();
2159 bool easyAssign=true;
2160 const int *connI=_nodal_connec_index->getConstPointer();
2161 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2162 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2164 if(*it>=0 && *it<nbOfCells)
2166 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2170 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2171 throw INTERP_KERNEL::Exception(oss.str().c_str());
2176 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2181 DataArrayInt *arrOut=0,*arrIOut=0;
2182 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2185 setConnectivity(arrOut,arrIOut,true);
2189 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2191 checkConnectivityFullyDefined();
2192 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2193 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2194 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2195 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2197 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2198 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2199 throw INTERP_KERNEL::Exception(oss.str().c_str());
2201 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2202 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2204 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2205 throw INTERP_KERNEL::Exception(oss.str().c_str());
2207 int nbOfCells=getNumberOfCells();
2208 bool easyAssign=true;
2209 const int *connI=_nodal_connec_index->getConstPointer();
2210 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2212 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2214 if(it>=0 && it<nbOfCells)
2216 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2220 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2221 throw INTERP_KERNEL::Exception(oss.str().c_str());
2226 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2231 DataArrayInt *arrOut=0,*arrIOut=0;
2232 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2234 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2235 setConnectivity(arrOut,arrIOut,true);
2240 * Finds cells whose all nodes are in a given array of node ids.
2241 * \param [in] partBg - the array of node ids.
2242 * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2243 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2244 * cells. The caller is to delete this array using decrRef() as it is no
2246 * \throw If the coordinates array is not set.
2247 * \throw If the nodal connectivity of cells is not defined.
2248 * \throw If any cell id in \a partBg is not valid.
2250 * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2251 * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2253 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2255 DataArrayInt *cellIdsKept=0;
2256 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2257 cellIdsKept->setName(getName());
2262 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2263 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2264 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2265 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2267 * \param [in] begin input start of array of node ids.
2268 * \param [in] end input end of array of node ids.
2269 * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
2270 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2272 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2275 checkConnectivityFullyDefined();
2277 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2278 std::vector<bool> fastFinder(sz,false);
2279 for(const int *work=begin;work!=end;work++)
2280 if(*work>=0 && *work<sz)
2281 fastFinder[*work]=true;
2282 int nbOfCells=getNumberOfCells();
2283 const int *conn=getNodalConnectivity()->getConstPointer();
2284 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2285 for(int i=0;i<nbOfCells;i++)
2287 int ref=0,nbOfHit=0;
2288 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2292 if(fastFinder[*work2])
2295 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2296 cellIdsKept->pushBackSilent(i);
2298 cellIdsKeptArr=cellIdsKept.retn();
2302 * Finds cells whose all or some nodes are in a given array of node ids.
2303 * \param [in] begin - the array of node ids.
2304 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2305 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2306 * array \a begin are returned only, else cells whose any node is in the
2307 * array \a begin are returned.
2308 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2309 * cells. The caller is to delete this array using decrRef() as it is no more
2311 * \throw If the coordinates array is not set.
2312 * \throw If the nodal connectivity of cells is not defined.
2313 * \throw If any cell id in \a begin is not valid.
2315 * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2316 * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2318 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2320 DataArrayInt *cellIdsKept=0;
2321 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2322 cellIdsKept->setName(getName());
2327 Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
2328 copy are selected basing on specified node ids and the value of \a fullyIn
2329 parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the
2330 array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
2331 node is in the array of node ids. The created mesh shares the node coordinates array
2333 * \param [in] begin - the array of node ids.
2334 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2335 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2336 * array \a begin are copied, else cells whose any node is in the
2337 * array \a begin are copied.
2338 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2339 * to delete this mesh using decrRef() as it is no more needed.
2340 * \throw If the coordinates array is not set.
2341 * \throw If the nodal connectivity of cells is not defined.
2342 * \throw If any node id in \a begin is not valid.
2344 * \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
2345 * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
2347 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2349 DataArrayInt *cellIdsKept=0;
2350 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2352 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2356 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2357 * this->getMeshDimension(), that bound some cells of \a this mesh.
2358 * The cells of lower dimension to include to the result mesh are selected basing on
2359 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2360 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2361 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2362 * created mesh shares the node coordinates array with \a this mesh.
2363 * \param [in] begin - the array of node ids.
2364 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2365 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2366 * array \a begin are added, else cells whose any node is in the
2367 * array \a begin are added.
2368 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2369 * to delete this mesh using decrRef() as it is no more needed.
2370 * \throw If the coordinates array is not set.
2371 * \throw If the nodal connectivity of cells is not defined.
2372 * \throw If any node id in \a begin is not valid.
2374 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2375 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2377 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2380 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2381 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2382 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2383 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2387 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2388 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2389 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2390 * array of \a this mesh, else "free" nodes are removed from the result mesh
2391 * by calling zipCoords().
2392 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2393 * to delete this mesh using decrRef() as it is no more needed.
2394 * \throw If the coordinates array is not set.
2395 * \throw If the nodal connectivity of cells is not defined.
2397 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2398 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2400 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2402 DataArrayInt *desc=DataArrayInt::New();
2403 DataArrayInt *descIndx=DataArrayInt::New();
2404 DataArrayInt *revDesc=DataArrayInt::New();
2405 DataArrayInt *revDescIndx=DataArrayInt::New();
2407 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2410 descIndx->decrRef();
2411 int nbOfCells=meshDM1->getNumberOfCells();
2412 const int *revDescIndxC=revDescIndx->getConstPointer();
2413 std::vector<int> boundaryCells;
2414 for(int i=0;i<nbOfCells;i++)
2415 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2416 boundaryCells.push_back(i);
2417 revDescIndx->decrRef();
2418 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2423 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2424 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2425 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
2427 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2429 checkFullyDefined();
2430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2435 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2436 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2438 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2439 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2440 const int *revDescPtr=revDesc->getConstPointer();
2441 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2442 int nbOfCells=getNumberOfCells();
2443 std::vector<bool> ret1(nbOfCells,false);
2445 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2446 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2447 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2449 DataArrayInt *ret2=DataArrayInt::New();
2451 int *ret2Ptr=ret2->getPointer();
2453 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2456 ret2->setName("BoundaryCells");
2461 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2462 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2463 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2464 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2466 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2467 * This method method returns cells ids set s = s1 + s2 where :
2469 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2470 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2472 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2473 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2475 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2476 * \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
2477 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2479 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2481 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2482 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2483 checkConnectivityFullyDefined();
2484 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2485 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2486 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2487 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2489 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2491 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2492 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2493 DataArrayInt *idsOtherInConsti=0;
2494 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2495 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2497 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2499 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2500 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2501 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2502 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2503 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2504 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2506 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2507 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2508 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2509 neighThisPartAuto=0;
2510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2511 const int li[2]={0,1};
2512 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2513 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2517 cellIdsRk0=s0arr.retn();
2518 cellIdsRk1=s_renum1.retn();
2522 * 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
2523 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2525 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2527 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2529 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2531 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2534 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2535 revDesc=0; desc=0; descIndx=0;
2536 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2538 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2542 * Finds nodes lying on the boundary of \a this mesh.
2543 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2544 * nodes. The caller is to delete this array using decrRef() as it is no
2546 * \throw If the coordinates array is not set.
2547 * \throw If the nodal connectivity of cells is node defined.
2549 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2550 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2552 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2554 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2555 return skin->computeFetchedNodeIds();
2558 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2561 return const_cast<MEDCouplingUMesh *>(this);
2565 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2566 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
2567 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2568 * array is modified accordingly.
2569 * \param [in] newNodeNumbers - a permutation array, of length \a
2570 * this->getNumberOfNodes(), in "Old to New" mode.
2571 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2572 * \param [in] newNbOfNodes - number of nodes remaining after renumbering.
2573 * \throw If the coordinates array is not set.
2574 * \throw If the nodal connectivity of cells is not defined.
2576 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2577 * \ref py_mcumesh_renumberNodes "Here is a Python example".
2579 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2581 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2582 renumberNodesInConn(newNodeNumbers);
2586 * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2587 * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
2588 * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2589 * array is modified accordingly. In contrast to renumberNodes(), location
2590 * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
2591 * \param [in] newNodeNumbers - a permutation array, of length \a
2592 * this->getNumberOfNodes(), in "Old to New" mode.
2593 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2594 * \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
2595 * actually one more than the maximal id in \a newNodeNumbers.
2596 * \throw If the coordinates array is not set.
2597 * \throw If the nodal connectivity of cells is not defined.
2599 * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2600 * \ref py_mcumesh_renumberNodes "Here is a Python example".
2602 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2604 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2605 renumberNodesInConn(newNodeNumbers);
2609 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2610 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2611 * 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.
2612 * 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.
2613 * 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.
2615 * \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
2616 * parameter is altered during the call.
2617 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2618 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2619 * \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.
2621 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2623 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2624 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2626 checkFullyDefined();
2627 otherDimM1OnSameCoords.checkFullyDefined();
2628 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2629 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2630 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2632 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2633 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2635 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2636 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2637 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2641 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2643 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2645 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2646 DataArrayInt *idsTmp=0;
2647 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2648 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2650 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2651 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2652 DataArrayInt *tmp0=0,*tmp1=0;
2653 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2654 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2658 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2659 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2661 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2662 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2663 nodeIdsToDuplicate=s3.retn();
2667 * This method operates a modification of the connectivity and coords in \b this.
2668 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2669 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2670 * 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
2671 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2672 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2674 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2676 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2677 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2679 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2681 int nbOfNodes=getNumberOfNodes();
2682 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2683 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2687 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2688 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2689 * This method is a generalization of shiftNodeNumbersInConn().
2690 * \warning This method performs no check of validity of new ids. **Use it with care !**
2691 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2692 * this->getNumberOfNodes(), in "Old to New" mode.
2693 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2694 * \throw If the nodal connectivity of cells is not defined.
2696 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2697 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2699 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2701 checkConnectivityFullyDefined();
2702 int *conn=getNodalConnectivity()->getPointer();
2703 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2704 int nbOfCells=getNumberOfCells();
2705 for(int i=0;i<nbOfCells;i++)
2706 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2708 int& node=conn[iconn];
2709 if(node>=0)//avoid polyhedron separator
2711 node=newNodeNumbersO2N[node];
2714 _nodal_connec->declareAsNew();
2719 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2720 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2721 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2723 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2725 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2727 checkConnectivityFullyDefined();
2728 int *conn=getNodalConnectivity()->getPointer();
2729 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2730 int nbOfCells=getNumberOfCells();
2731 for(int i=0;i<nbOfCells;i++)
2732 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2734 int& node=conn[iconn];
2735 if(node>=0)//avoid polyhedron separator
2740 _nodal_connec->declareAsNew();
2745 * This method operates a modification of the connectivity in \b this.
2746 * 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.
2747 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2748 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2749 * 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
2750 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2751 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2753 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2754 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2756 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2757 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2758 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2760 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2762 checkConnectivityFullyDefined();
2763 std::map<int,int> m;
2765 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2767 int *conn=getNodalConnectivity()->getPointer();
2768 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2769 int nbOfCells=getNumberOfCells();
2770 for(int i=0;i<nbOfCells;i++)
2771 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2773 int& node=conn[iconn];
2774 if(node>=0)//avoid polyhedron separator
2776 std::map<int,int>::iterator it=m.find(node);
2785 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2787 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2788 * After the call of this method the number of cells remains the same as before.
2790 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2791 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2792 * be strictly in [0;this->getNumberOfCells()).
2794 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2795 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2796 * should be contained in[0;this->getNumberOfCells()).
2798 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2800 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2802 checkConnectivityFullyDefined();
2803 int nbCells=getNumberOfCells();
2804 const int *array=old2NewBg;
2806 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2808 const int *conn=_nodal_connec->getConstPointer();
2809 const int *connI=_nodal_connec_index->getConstPointer();
2810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2811 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2812 newConn->copyStringInfoFrom(*_nodal_connec);
2813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2814 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2815 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2817 int *newC=newConn->getPointer();
2818 int *newCI=newConnI->getPointer();
2821 for(int i=0;i<nbCells;i++)
2823 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2824 int nbOfElts=connI[pos+1]-connI[pos];
2825 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2830 setConnectivity(newConn,newConnI);
2832 delete [] const_cast<int *>(array);
2836 * Finds cells whose bounding boxes intersect a given bounding box.
2837 * \param [in] bbox - an array defining the bounding box via coordinates of its
2838 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2840 * \param [in] eps - a factor used to increase size of the bounding box of cell
2841 * before comparing it with \a bbox. This factor is multiplied by the maximal
2842 * extent of the bounding box of cell to produce an addition to this bounding box.
2843 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2844 * cells. The caller is to delete this array using decrRef() as it is no more
2846 * \throw If the coordinates array is not set.
2847 * \throw If the nodal connectivity of cells is not defined.
2849 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2850 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2852 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2855 if(getMeshDimension()==-1)
2857 elems->pushBackSilent(0);
2858 return elems.retn();
2860 int dim=getSpaceDimension();
2861 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2862 const int* conn = getNodalConnectivity()->getConstPointer();
2863 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2864 const double* coords = getCoords()->getConstPointer();
2865 int nbOfCells=getNumberOfCells();
2866 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2868 for (int i=0; i<dim; i++)
2870 elem_bb[i*2]=std::numeric_limits<double>::max();
2871 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2874 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2876 int node= conn[inode];
2877 if(node>=0)//avoid polyhedron separator
2879 for (int idim=0; idim<dim; idim++)
2881 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2883 elem_bb[idim*2] = coords[node*dim+idim] ;
2885 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2887 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2892 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2893 elems->pushBackSilent(ielem);
2895 return elems.retn();
2899 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2900 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2901 * added in 'elems' parameter.
2903 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2906 if(getMeshDimension()==-1)
2908 elems->pushBackSilent(0);
2909 return elems.retn();
2911 int dim=getSpaceDimension();
2912 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2913 const int* conn = getNodalConnectivity()->getConstPointer();
2914 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2915 const double* coords = getCoords()->getConstPointer();
2916 int nbOfCells=getNumberOfCells();
2917 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2919 for (int i=0; i<dim; i++)
2921 elem_bb[i*2]=std::numeric_limits<double>::max();
2922 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2925 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2927 int node= conn[inode];
2928 if(node>=0)//avoid polyhedron separator
2930 for (int idim=0; idim<dim; idim++)
2932 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2934 elem_bb[idim*2] = coords[node*dim+idim] ;
2936 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2938 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2943 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2944 elems->pushBackSilent(ielem);
2946 return elems.retn();
2950 * Returns a type of a cell by its id.
2951 * \param [in] cellId - the id of the cell of interest.
2952 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2953 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2955 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2957 const int *ptI=_nodal_connec_index->getConstPointer();
2958 const int *pt=_nodal_connec->getConstPointer();
2959 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2960 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2963 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2964 throw INTERP_KERNEL::Exception(oss.str().c_str());
2969 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2970 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2971 * The coordinates array is not considered here.
2973 * \param [in] type the geometric type
2974 * \return cell ids in this having geometric type \a type.
2976 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2981 checkConnectivityFullyDefined();
2982 int nbCells=getNumberOfCells();
2983 int mdim=getMeshDimension();
2984 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2985 if(mdim!=(int)cm.getDimension())
2986 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2987 const int *ptI=_nodal_connec_index->getConstPointer();
2988 const int *pt=_nodal_connec->getConstPointer();
2989 for(int i=0;i<nbCells;i++)
2991 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2992 ret->pushBackSilent(i);
2998 * Returns nb of cells having the geometric type 'type'.
3000 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3002 const int *ptI=_nodal_connec_index->getConstPointer();
3003 const int *pt=_nodal_connec->getConstPointer();
3004 int nbOfCells=getNumberOfCells();
3006 for(int i=0;i<nbOfCells;i++)
3007 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3013 * Returns the nodal connectivity of a given cell.
3014 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3015 * all returned node ids can be used in getCoordinatesOfNode().
3016 * \param [in] cellId - an id of the cell of interest.
3017 * \param [in,out] conn - a vector where the node ids are appended. It is not
3018 * cleared before the appending.
3019 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3021 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3023 const int *ptI=_nodal_connec_index->getConstPointer();
3024 const int *pt=_nodal_connec->getConstPointer();
3025 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3030 std::string MEDCouplingUMesh::simpleRepr() const
3032 static const char msg0[]="No coordinates specified !";
3033 std::ostringstream ret;
3034 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3035 ret << "Description of mesh : \"" << getDescription() << "\"\n";
3037 double tt=getTime(tmpp1,tmpp2);
3038 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3039 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
3041 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3043 { ret << " Mesh dimension has not been set or is invalid !"; }
3046 const int spaceDim=getSpaceDimension();
3047 ret << spaceDim << "\nInfo attached on space dimension : ";
3048 for(int i=0;i<spaceDim;i++)
3049 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3053 ret << msg0 << "\n";
3054 ret << "Number of nodes : ";
3056 ret << getNumberOfNodes() << "\n";
3058 ret << msg0 << "\n";
3059 ret << "Number of cells : ";
3060 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3061 ret << getNumberOfCells() << "\n";
3063 ret << "No connectivity specified !" << "\n";
3064 ret << "Cell types present : ";
3065 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3067 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3068 ret << cm.getRepr() << " ";
3074 std::string MEDCouplingUMesh::advancedRepr() const
3076 std::ostringstream ret;
3077 ret << simpleRepr();
3078 ret << "\nCoordinates array : \n___________________\n\n";
3080 _coords->reprWithoutNameStream(ret);
3082 ret << "No array set !\n";
3083 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3084 reprConnectivityOfThisLL(ret);
3089 * This method returns a C++ code that is a dump of \a this.
3090 * This method will throw if this is not fully defined.
3092 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
3094 static const char coordsName[]="coords";
3095 static const char connName[]="conn";
3096 static const char connIName[]="connI";
3097 checkFullyDefined();
3098 std::ostringstream ret; ret << "// coordinates" << std::endl;
3099 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3100 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3101 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3102 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3103 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3104 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3105 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3109 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3111 std::ostringstream ret;
3112 reprConnectivityOfThisLL(ret);
3117 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
3118 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3119 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3122 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3123 * This method analyzes the 3 arrays of 'this'. For each the following behaviour is done : if the array is null a newly one is created
3124 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3126 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
3128 int mdim=getMeshDimension();
3130 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3131 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3133 bool needToCpyCT=true;
3136 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3144 if(!_nodal_connec_index)
3146 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3151 tmp2=_nodal_connec_index;
3154 ret->setConnectivity(tmp1,tmp2,false);
3159 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3160 ret->setCoords(coords);
3163 ret->setCoords(_coords);
3167 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3169 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3171 int nbOfCells=getNumberOfCells();
3172 const int *c=_nodal_connec->getConstPointer();
3173 const int *ci=_nodal_connec_index->getConstPointer();
3174 for(int i=0;i<nbOfCells;i++)
3176 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3177 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3178 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3183 stream << "Connectivity not defined !\n";
3186 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3188 const int *ptI=_nodal_connec_index->getConstPointer();
3189 const int *pt=_nodal_connec->getConstPointer();
3190 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3191 return ptI[cellId+1]-ptI[cellId]-1;
3193 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3197 * Returns types of cells of the specified part of \a this mesh.
3198 * This method avoids computing sub-mesh explicitely to get its types.
3199 * \param [in] begin - an array of cell ids of interest.
3200 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3201 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3202 * describing the cell types.
3203 * \throw If the coordinates array is not set.
3204 * \throw If the nodal connectivity of cells is not defined.
3207 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
3209 checkFullyDefined();
3210 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3211 const int *conn=_nodal_connec->getConstPointer();
3212 const int *connIndex=_nodal_connec_index->getConstPointer();
3213 for(const int *w=begin;w!=end;w++)
3214 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3219 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3220 * a set of types of cells constituting \a this mesh.
3221 * This method is for advanced users having prepared their connectivity before. For
3222 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3223 * \param [in] conn - the nodal connectivity array.
3224 * \param [in] connIndex - the nodal connectivity index array.
3225 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3228 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3230 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3231 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3232 if(isComputingTypes)
3238 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
3239 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3241 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3242 _nodal_connec(0),_nodal_connec_index(0),
3243 _types(other._types)
3245 if(other._nodal_connec)
3246 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3247 if(other._nodal_connec_index)
3248 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3251 MEDCouplingUMesh::~MEDCouplingUMesh()
3254 _nodal_connec->decrRef();
3255 if(_nodal_connec_index)
3256 _nodal_connec_index->decrRef();
3260 * Recomputes a set of cell types of \a this mesh. For more info see
3261 * \ref MEDCouplingUMeshNodalConnectivity.
3263 void MEDCouplingUMesh::computeTypes()
3265 if(_nodal_connec && _nodal_connec_index)
3268 const int *conn=_nodal_connec->getConstPointer();
3269 const int *connIndex=_nodal_connec_index->getConstPointer();
3270 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3272 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3273 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3278 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3280 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3282 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3283 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3287 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3289 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3291 if(!_nodal_connec_index || !_nodal_connec)
3292 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3296 * Returns a number of cells constituting \a this mesh.
3297 * \return int - the number of cells in \a this mesh.
3298 * \throw If the nodal connectivity of cells is not defined.
3300 int MEDCouplingUMesh::getNumberOfCells() const
3302 if(_nodal_connec_index)
3303 return _nodal_connec_index->getNumberOfTuples()-1;
3308 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3312 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3313 * mesh. For more info see \ref MEDCouplingMeshesPage.
3314 * \return int - the dimension of \a this mesh.
3315 * \throw If the mesh dimension is not defined using setMeshDimension().
3317 int MEDCouplingUMesh::getMeshDimension() const
3320 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3325 * Returns a length of the nodal connectivity array.
3326 * This method is for test reason. Normally the integer returned is not useable by
3327 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3328 * \return int - the length of the nodal connectivity array.
3330 int MEDCouplingUMesh::getMeshLength() const
3332 return _nodal_connec->getNbOfElems();
3336 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3338 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3340 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3341 tinyInfo.push_back(getMeshDimension());
3342 tinyInfo.push_back(getNumberOfCells());
3344 tinyInfo.push_back(getMeshLength());
3346 tinyInfo.push_back(-1);
3350 * First step of unserialization process.
3352 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3354 return tinyInfo[6]<=0;
3358 * Second step of serialization process.
3359 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3361 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3363 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3365 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3369 * Third and final step of serialization process.
3371 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3373 MEDCouplingPointSet::serialize(a1,a2);
3374 if(getMeshDimension()>-1)
3376 a1=DataArrayInt::New();
3377 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3378 int *ptA1=a1->getPointer();
3379 const int *conn=getNodalConnectivity()->getConstPointer();
3380 const int *index=getNodalConnectivityIndex()->getConstPointer();
3381 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3382 std::copy(conn,conn+getMeshLength(),ptA1);
3389 * Second and final unserialization process.
3390 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3392 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3394 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3395 setMeshDimension(tinyInfo[5]);
3399 const int *recvBuffer=a1->getConstPointer();
3400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3401 myConnecIndex->alloc(tinyInfo[6]+1,1);
3402 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3404 myConnec->alloc(tinyInfo[7],1);
3405 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3406 setConnectivity(myConnec, myConnecIndex);
3411 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3412 * CellIds are given using range specified by a start an end and step.
3414 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3416 checkFullyDefined();
3417 int ncell=getNumberOfCells();
3418 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3419 ret->_mesh_dim=_mesh_dim;
3420 ret->setCoords(_coords);
3421 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3422 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3423 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3425 const int *conn=_nodal_connec->getConstPointer();
3426 const int *connIndex=_nodal_connec_index->getConstPointer();
3427 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3429 if(work>=0 && work<ncell)
3431 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3435 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3436 throw INTERP_KERNEL::Exception(oss.str().c_str());
3439 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3440 int *newConnPtr=newConn->getPointer();
3441 std::set<INTERP_KERNEL::NormalizedCellType> types;
3443 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3445 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3446 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3448 ret->setConnectivity(newConn,newConnI,false);
3450 ret->copyTinyInfoFrom(this);
3455 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3456 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3457 * The return newly allocated mesh will share the same coordinates as 'this'.
3459 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3461 checkFullyDefined();
3462 int ncell=getNumberOfCells();
3463 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3464 ret->_mesh_dim=_mesh_dim;
3465 ret->setCoords(_coords);
3466 std::size_t nbOfElemsRet=std::distance(begin,end);
3467 int *connIndexRet=new int[nbOfElemsRet+1];
3469 const int *conn=_nodal_connec->getConstPointer();
3470 const int *connIndex=_nodal_connec_index->getConstPointer();
3472 for(const int *work=begin;work!=end;work++,newNbring++)
3474 if(*work>=0 && *work<ncell)
3475 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3478 delete [] connIndexRet;
3479 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3480 throw INTERP_KERNEL::Exception(oss.str().c_str());
3483 int *connRet=new int[connIndexRet[nbOfElemsRet]];
3484 int *connRetWork=connRet;
3485 std::set<INTERP_KERNEL::NormalizedCellType> types;
3486 for(const int *work=begin;work!=end;work++)
3488 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3489 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3491 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3492 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3493 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3494 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3495 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3497 ret->copyTinyInfoFrom(this);
3502 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3504 * For 1D cells, the returned field contains lengths.<br>
3505 * For 2D cells, the returned field contains areas.<br>
3506 * For 3D cells, the returned field contains volumes.
3507 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3508 * orientation, i.e. the volume is always positive.
3509 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3510 * and one time . The caller is to delete this field using decrRef() as it is no
3513 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3515 std::string name="MeasureOfMesh_";
3517 int nbelem=getNumberOfCells();
3518 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3519 field->setName(name.c_str());
3520 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3521 array->alloc(nbelem,1);
3522 double *area_vol=array->getPointer();
3523 field->setArray(array) ; array=0;
3524 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3525 field->synchronizeTimeWithMesh();
3526 if(getMeshDimension()!=-1)
3529 INTERP_KERNEL::NormalizedCellType type;
3530 int dim_space=getSpaceDimension();
3531 const double *coords=getCoords()->getConstPointer();
3532 const int *connec=getNodalConnectivity()->getConstPointer();
3533 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3534 for(int iel=0;iel<nbelem;iel++)
3536 ipt=connec_index[iel];
3537 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3538 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);
3541 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3545 area_vol[0]=std::numeric_limits<double>::max();
3547 return field.retn();
3551 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3553 * For 1D cells, the returned array contains lengths.<br>
3554 * For 2D cells, the returned array contains areas.<br>
3555 * For 3D cells, the returned array contains volumes.
3556 * This method avoids building explicitly a part of \a this mesh to perform the work.
3557 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3558 * orientation, i.e. the volume is always positive.
3559 * \param [in] begin - an array of cell ids of interest.
3560 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3561 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3562 * delete this array using decrRef() as it is no more needed.
3564 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3565 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3566 * \sa getMeasureField()
3568 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3570 std::string name="PartMeasureOfMesh_";
3572 int nbelem=(int)std::distance(begin,end);
3573 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3574 array->setName(name.c_str());
3575 array->alloc(nbelem,1);
3576 double *area_vol=array->getPointer();
3577 if(getMeshDimension()!=-1)
3580 INTERP_KERNEL::NormalizedCellType type;
3581 int dim_space=getSpaceDimension();
3582 const double *coords=getCoords()->getConstPointer();
3583 const int *connec=getNodalConnectivity()->getConstPointer();
3584 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3585 for(const int *iel=begin;iel!=end;iel++)
3587 ipt=connec_index[*iel];
3588 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3589 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3592 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3596 area_vol[0]=std::numeric_limits<double>::max();
3598 return array.retn();
3602 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3603 * \a this one. The returned field contains the dual cell volume for each corresponding
3604 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3605 * the dual mesh in P1 sens of \a this.<br>
3606 * For 1D cells, the returned field contains lengths.<br>
3607 * For 2D cells, the returned field contains areas.<br>
3608 * For 3D cells, the returned field contains volumes.
3609 * This method is useful to check "P1*" conservative interpolators.
3610 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3611 * orientation, i.e. the volume is always positive.
3612 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3613 * nodes and one time. The caller is to delete this array using decrRef() as
3614 * it is no more needed.
3616 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3618 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3619 std::string name="MeasureOnNodeOfMesh_";
3621 int nbNodes=getNumberOfNodes();
3622 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3623 double cst=1./((double)getMeshDimension()+1.);
3624 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3625 array->alloc(nbNodes,1);
3626 double *valsToFill=array->getPointer();
3627 std::fill(valsToFill,valsToFill+nbNodes,0.);
3628 const double *values=tmp->getArray()->getConstPointer();
3629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3630 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3631 getReverseNodalConnectivity(da,daInd);
3632 const int *daPtr=da->getConstPointer();
3633 const int *daIPtr=daInd->getConstPointer();
3634 for(int i=0;i<nbNodes;i++)
3635 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3636 valsToFill[i]+=cst*values[*cell];
3638 ret->setArray(array);
3643 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3644 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3645 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3646 * and are normalized.
3647 * <br> \a this can be either
3648 * - a 2D mesh in 2D or 3D space or
3649 * - an 1D mesh in 2D space.
3651 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3652 * cells and one time. The caller is to delete this field using decrRef() as
3653 * it is no more needed.
3654 * \throw If the nodal connectivity of cells is not defined.
3655 * \throw If the coordinates array is not set.
3656 * \throw If the mesh dimension is not set.
3657 * \throw If the mesh and space dimension is not as specified above.
3659 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3661 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3662 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3663 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3664 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3665 int nbOfCells=getNumberOfCells();
3666 int nbComp=getMeshDimension()+1;
3667 array->alloc(nbOfCells,nbComp);
3668 double *vals=array->getPointer();
3669 const int *connI=_nodal_connec_index->getConstPointer();
3670 const int *conn=_nodal_connec->getConstPointer();
3671 const double *coords=_coords->getConstPointer();
3672 if(getMeshDimension()==2)
3674 if(getSpaceDimension()==3)
3676 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3677 const double *locPtr=loc->getConstPointer();
3678 for(int i=0;i<nbOfCells;i++,vals+=3)
3680 int offset=connI[i];
3681 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3682 double n=INTERP_KERNEL::norm<3>(vals);
3683 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3688 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3689 const double *isAbsPtr=isAbs->getArray()->begin();
3690 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3691 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3694 else//meshdimension==1
3697 for(int i=0;i<nbOfCells;i++)
3699 int offset=connI[i];
3700 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3701 double n=INTERP_KERNEL::norm<2>(tmp);
3702 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3707 ret->setArray(array);
3709 ret->synchronizeTimeWithSupport();
3714 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3715 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3716 * and are normalized.
3717 * <br> \a this can be either
3718 * - a 2D mesh in 2D or 3D space or
3719 * - an 1D mesh in 2D space.
3721 * This method avoids building explicitly a part of \a this mesh to perform the work.
3722 * \param [in] begin - an array of cell ids of interest.
3723 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3724 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3725 * cells and one time. The caller is to delete this field using decrRef() as
3726 * it is no more needed.
3727 * \throw If the nodal connectivity of cells is not defined.
3728 * \throw If the coordinates array is not set.
3729 * \throw If the mesh dimension is not set.
3730 * \throw If the mesh and space dimension is not as specified above.
3731 * \sa buildOrthogonalField()
3733 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3734 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3736 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3738 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3739 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3740 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3741 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3742 std::size_t nbelems=std::distance(begin,end);
3743 int nbComp=getMeshDimension()+1;
3744 array->alloc((int)nbelems,nbComp);
3745 double *vals=array->getPointer();
3746 const int *connI=_nodal_connec_index->getConstPointer();
3747 const int *conn=_nodal_connec->getConstPointer();
3748 const double *coords=_coords->getConstPointer();
3749 if(getMeshDimension()==2)
3751 if(getSpaceDimension()==3)
3753 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3754 const double *locPtr=loc->getConstPointer();
3755 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3757 int offset=connI[*i];
3758 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3759 double n=INTERP_KERNEL::norm<3>(vals);
3760 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3765 for(std::size_t i=0;i<nbelems;i++)
3766 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3769 else//meshdimension==1
3772 for(const int *i=begin;i!=end;i++)
3774 int offset=connI[*i];
3775 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3776 double n=INTERP_KERNEL::norm<2>(tmp);
3777 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3782 ret->setArray(array);
3784 ret->synchronizeTimeWithSupport();
3789 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3790 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3791 * and are \b not normalized.
3792 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3793 * cells and one time. The caller is to delete this field using decrRef() as
3794 * it is no more needed.
3795 * \throw If the nodal connectivity of cells is not defined.
3796 * \throw If the coordinates array is not set.
3797 * \throw If \a this->getMeshDimension() != 1.
3798 * \throw If \a this mesh includes cells of type other than SEG2.
3800 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3802 if(getMeshDimension()!=1)
3803 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3804 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3805 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3806 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3807 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3808 int nbOfCells=getNumberOfCells();
3809 int spaceDim=getSpaceDimension();
3810 array->alloc(nbOfCells,spaceDim);
3811 double *pt=array->getPointer();
3812 const double *coo=getCoords()->getConstPointer();
3813 std::vector<int> conn;
3815 for(int i=0;i<nbOfCells;i++)
3818 getNodeIdsOfCell(i,conn);
3819 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3821 ret->setArray(array);
3823 ret->synchronizeTimeWithSupport();
3828 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3829 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3830 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3831 * from. If a result face is shared by two 3D cells, then the face in included twice in
3833 * \param [in] origin - 3 components of a point defining location of the plane.
3834 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3835 * must be greater than 1e-6.
3836 * \param [in] eps - half-thickness of the plane.
3837 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3838 * producing correspondent 2D cells. The caller is to delete this array
3839 * using decrRef() as it is no more needed.
3840 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3841 * not share the node coordinates array with \a this mesh. The caller is to
3842 * delete this mesh using decrRef() as it is no more needed.
3843 * \throw If the coordinates array is not set.
3844 * \throw If the nodal connectivity of cells is not defined.
3845 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3846 * \throw If magnitude of \a vec is less than 1e-6.
3847 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3848 * \throw If \a this includes quadratic cells.
3850 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3852 checkFullyDefined();
3853 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3854 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3855 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3856 if(candidates->empty())
3857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3858 std::vector<int> nodes;
3859 DataArrayInt *cellIds1D=0;
3860 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3861 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3866 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3867 revDesc2=0; revDescIndx2=0;
3868 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3869 revDesc1=0; revDescIndx1=0;
3870 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3873 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3874 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3876 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3877 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3878 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3879 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3880 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3882 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3883 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3884 if(cellIds2->empty())
3885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3886 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3887 ret->setCoords(mDesc1->getCoords());
3888 ret->setConnectivity(conn,connI,true);
3889 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3894 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3895 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
3896 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3898 * \param [in] origin - 3 components of a point defining location of the plane.
3899 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3900 * must be greater than 1e-6.
3901 * \param [in] eps - half-thickness of the plane.
3902 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3903 * producing correspondent segments. The caller is to delete this array
3904 * using decrRef() as it is no more needed.
3905 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3906 * mesh in 3D space. This mesh does not share the node coordinates array with
3907 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3909 * \throw If the coordinates array is not set.
3910 * \throw If the nodal connectivity of cells is not defined.
3911 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3912 * \throw If magnitude of \a vec is less than 1e-6.
3913 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3914 * \throw If \a this includes quadratic cells.
3916 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3918 checkFullyDefined();
3919 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3922 if(candidates->empty())
3923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3924 std::vector<int> nodes;
3925 DataArrayInt *cellIds1D=0;
3926 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3927 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3930 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3931 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3932 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3933 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3936 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3937 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3939 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3940 int ncellsSub=subMesh->getNumberOfCells();
3941 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3942 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3943 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3944 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3945 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3947 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3948 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3949 for(int i=0;i<ncellsSub;i++)
3951 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3953 if(cut3DSurf[i].first!=-2)
3955 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3956 connI->pushBackSilent(conn->getNumberOfTuples());
3957 cellIds2->pushBackSilent(i);
3961 int cellId3DSurf=cut3DSurf[i].second;
3962 int offset=nodalI[cellId3DSurf]+1;
3963 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3964 for(int j=0;j<nbOfEdges;j++)
3966 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3967 connI->pushBackSilent(conn->getNumberOfTuples());
3968 cellIds2->pushBackSilent(cellId3DSurf);
3973 if(cellIds2->empty())
3974 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3975 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3976 ret->setCoords(mDesc1->getCoords());
3977 ret->setConnectivity(conn,connI,true);
3978 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3983 * Finds cells whose bounding boxes intersect a given plane.
3984 * \param [in] origin - 3 components of a point defining location of the plane.
3985 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3986 * must be greater than 1e-6.
3987 * \param [in] eps - half-thickness of the plane.
3988 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3989 * cells. The caller is to delete this array using decrRef() as it is no more
3991 * \throw If the coordinates array is not set.
3992 * \throw If the nodal connectivity of cells is not defined.
3993 * \throw If \a this->getSpaceDimension() != 3.
3994 * \throw If magnitude of \a vec is less than 1e-6.
3995 * \sa buildSlice3D()
3997 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3999 checkFullyDefined();
4000 if(getSpaceDimension()!=3)
4001 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4002 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4004 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4006 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4007 double angle=acos(vec[2]/normm);
4008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
4012 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
4013 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4014 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4016 mw->getBoundingBox(bbox);
4017 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4018 cellIds=mw->getCellsInBoundingBox(bbox,eps);
4022 getBoundingBox(bbox);
4023 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4024 cellIds=getCellsInBoundingBox(bbox,eps);
4026 return cellIds.retn();
4030 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4031 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4032 * No consideration of coordinate is done by this method.
4033 * 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)
4034 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
4036 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
4038 if(getMeshDimension()!=1)
4039 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4040 int nbCells=getNumberOfCells();
4042 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4043 const int *connI=_nodal_connec_index->getConstPointer();
4044 const int *conn=_nodal_connec->getConstPointer();
4045 int ref=conn[connI[0]+2];
4046 for(int i=1;i<nbCells;i++)
4048 if(conn[connI[i]+1]!=ref)
4050 ref=conn[connI[i]+2];
4056 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4057 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4058 * @param pt reference point of the line
4059 * @param v normalized director vector of the line
4060 * @param eps max precision before throwing an exception
4061 * @param res output of size this->getNumberOfCells
4063 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4065 if(getMeshDimension()!=1)
4066 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4067 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4068 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4069 if(getSpaceDimension()!=3)
4070 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4071 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4072 const double *fPtr=f->getArray()->getConstPointer();
4074 for(int i=0;i<getNumberOfCells();i++)
4076 const double *tmp1=fPtr+3*i;
4077 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4078 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4079 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4080 double n1=INTERP_KERNEL::norm<3>(tmp);
4081 n1/=INTERP_KERNEL::norm<3>(tmp1);
4083 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4085 const double *coo=getCoords()->getConstPointer();
4086 for(int i=0;i<getNumberOfNodes();i++)
4088 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4089 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4090 res[i]=std::accumulate(tmp,tmp+3,0.);
4095 * This method computes the distance from a point \a pt to \a this and the first \a cellId and \a nodeId in \a this corresponding to the returned distance.
4096 * \a this is expected to be a mesh so that its space dimension is equal to its
4097 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4098 * 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).
4100 * This method firstly find the closer node in \a this to the requested point whose coordinates are defined by [ \a ptBg, \a ptEnd ). Then for this node found
4101 * the cells sharing this node (if any) are considered to find if the distance to these cell are smaller than the result found previously. If no cells are linked
4102 * to the node that minimizes distance with the input point then -1 is returned in cellId.
4104 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4105 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4107 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4108 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4109 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4110 * \return the positive value of the distance.
4111 * \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
4113 * \sa DataArrayDouble::distanceToTuple
4115 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
4117 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4118 if(meshDim!=spaceDim-1)
4119 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4120 if(meshDim!=2 && meshDim!=1)
4121 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4122 checkFullyDefined();
4123 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4124 { 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()); }
4126 double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
4128 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
4129 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
4134 distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
4139 distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
4143 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4151 * \param [in] pt the start pointer (included) of the coordinates of the point
4152 * \param [in] cellIds
4153 * \param [in,out] ret0 the min distance between \a this and the external input point
4154 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4155 * \sa MEDCouplingUMesh::distanceToPoint
4157 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
4159 const double *coords=_coords->getConstPointer();
4161 if(cellIds->empty())
4163 const int *ptr=_nodal_connec->getConstPointer();
4164 const int *ptrI=_nodal_connec_index->getConstPointer();
4165 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
4167 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
4169 case INTERP_KERNEL::NORM_TRI3:
4171 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
4173 { ret0=tmp; cellId=*zeCell; }
4176 case INTERP_KERNEL::NORM_QUAD4:
4177 case INTERP_KERNEL::NORM_POLYGON:
4179 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
4181 { ret0=tmp; cellId=*zeCell; }
4185 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4191 * \param [in] pt the start pointer (included) of the coordinates of the point
4192 * \param [in] cellIds
4193 * \param [in,out] ret0 the min distance between \a this and the external input point
4194 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4195 * \sa MEDCouplingUMesh::distanceToPoint
4197 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
4199 const double *coords=_coords->getConstPointer();
4200 if(cellIds->empty())
4201 { cellId=-1; return; }
4202 const int *ptr=_nodal_connec->getConstPointer();
4203 const int *ptrI=_nodal_connec_index->getConstPointer();
4204 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
4206 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
4208 case INTERP_KERNEL::NORM_SEG2:
4210 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
4211 if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
4213 { ret0=tmp; cellId=*zeCell; }
4217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4223 * Finds cells in contact with a ball (i.e. a point with precision).
4224 * \warning This method is suitable if the caller intends to evaluate only one
4225 * point, for more points getCellsContainingPoints() is recommended as it is
4227 * \param [in] pos - array of coordinates of the ball central point.
4228 * \param [in] eps - ball radius.
4229 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4230 * if there are no such cells.
4231 * \throw If the coordinates array is not set.
4232 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4234 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4236 std::vector<int> elts;
4237 getCellsContainingPoint(pos,eps,elts);
4240 return elts.front();
4244 * Finds cells in contact with a ball (i.e. a point with precision).
4245 * \warning This method is suitable if the caller intends to evaluate only one
4246 * point, for more points getCellsContainingPoints() is recommended as it is
4248 * \param [in] pos - array of coordinates of the ball central point.
4249 * \param [in] eps - ball radius.
4250 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
4251 * before inserting ids.
4252 * \throw If the coordinates array is not set.
4253 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4255 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4256 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4258 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4260 std::vector<int> eltsIndex;
4261 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4266 namespace ParaMEDMEM
4268 template<const int SPACEDIMM>
4272 static const int MY_SPACEDIM=SPACEDIMM;
4273 static const int MY_MESHDIM=8;
4274 typedef int MyConnType;
4275 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4277 // useless, but for windows compilation ...
4278 const double* getCoordinatesPtr() const { return 0; }
4279 const int* getConnectivityPtr() const { return 0; }
4280 const int* getConnectivityIndexPtr() const { return 0; }
4281 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4285 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4287 INTERP_KERNEL::Edge *ret=0;
4290 case INTERP_KERNEL::NORM_SEG2:
4292 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4295 case INTERP_KERNEL::NORM_SEG3:
4297 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4298 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4299 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4300 bool colinearity=inters.areColinears();
4301 delete e1; delete e2;
4303 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4305 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4306 mapp2[bg[2]].second=false;
4310 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4316 * 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'.
4317 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4318 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4320 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4323 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.
4324 const double *coo=mDesc->getCoords()->getConstPointer();
4325 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4326 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4328 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4329 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4330 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4332 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4333 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4335 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4336 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4338 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4339 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4341 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4343 if((*it2).second.second)
4344 mapp[(*it2).second.first]=(*it2).first;
4345 ((*it2).second.first)->decrRef();
4350 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4354 int locId=nodeId-offset2;
4355 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4359 int locId=nodeId-offset1;
4360 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4362 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4365 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4366 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4367 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4369 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4371 int eltId1=abs(*desc1)-1;
4372 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4374 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4375 if(it==mappRev.end())
4377 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4388 template<int SPACEDIM>
4389 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4390 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4392 std::vector<double> bbox;
4393 eltsIndex.resize(nbOfPoints+1);
4396 getBoundingBoxForBBTree(bbox);
4397 int nbOfCells=getNumberOfCells();
4398 const int *conn=_nodal_connec->getConstPointer();
4399 const int *connI=_nodal_connec_index->getConstPointer();
4400 double bb[2*SPACEDIM];
4401 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4402 for(int i=0;i<nbOfPoints;i++)
4404 eltsIndex[i+1]=eltsIndex[i];
4405 for(int j=0;j<SPACEDIM;j++)
4407 bb[2*j]=pos[SPACEDIM*i+j];
4408 bb[2*j+1]=pos[SPACEDIM*i+j];
4410 std::vector<int> candidates;
4411 myTree.getIntersectingElems(bb,candidates);
4412 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4414 int sz=connI[(*iter)+1]-connI[*iter]-1;
4415 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4416 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4417 coords,conn+connI[*iter]+1,sz,eps))
4420 elts.push_back(*iter);
4426 * Finds cells in contact with several balls (i.e. points with precision).
4427 * This method is an extension of getCellContainingPoint() and
4428 * getCellsContainingPoint() for the case of multiple points.
4429 * \param [in] pos - an array of coordinates of points in full interlace mode :
4430 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4431 * this->getSpaceDimension() * \a nbOfPoints
4432 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4433 * \param [in] eps - radius of balls (i.e. the precision).
4434 * \param [in,out] elts - vector returning ids of found cells.
4435 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4436 * dividing cell ids in \a elts into groups each referring to one
4437 * point. Its every element (except the last one) is an index pointing to the
4438 * first id of a group of cells. For example cells in contact with the *i*-th
4439 * point are described by following range of indices:
4440 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4441 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4442 * Number of cells in contact with the *i*-th point is
4443 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4444 * \throw If the coordinates array is not set.
4445 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4447 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4448 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4450 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4451 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4453 int spaceDim=getSpaceDimension();
4454 int mDim=getMeshDimension();
4459 const double *coords=_coords->getConstPointer();
4460 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4467 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4469 else if(spaceDim==2)
4473 const double *coords=_coords->getConstPointer();
4474 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4477 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4479 else if(spaceDim==1)
4483 const double *coords=_coords->getConstPointer();
4484 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4487 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4490 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4494 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4495 * least two its edges intersect each other anywhere except their extremities. An
4496 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4497 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4498 * cleared before filling in.
4499 * \param [in] eps - precision.
4500 * \throw If \a this->getMeshDimension() != 2.
4501 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4503 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4505 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4506 if(getMeshDimension()!=2)
4507 throw INTERP_KERNEL::Exception(msg);
4508 int spaceDim=getSpaceDimension();
4509 if(spaceDim!=2 && spaceDim!=3)
4510 throw INTERP_KERNEL::Exception(msg);
4511 const int *conn=_nodal_connec->getConstPointer();
4512 const int *connI=_nodal_connec_index->getConstPointer();
4513 int nbOfCells=getNumberOfCells();
4514 std::vector<double> cell2DinS2;
4515 for(int i=0;i<nbOfCells;i++)
4517 int offset=connI[i];
4518 int nbOfNodesForCell=connI[i+1]-offset-1;
4519 if(nbOfNodesForCell<=3)
4521 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4522 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4523 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4530 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4532 * 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.
4533 * 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.
4535 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4536 * This convex envelop is computed using Jarvis march algorithm.
4537 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4538 * 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)
4539 * 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.
4541 * @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.
4543 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4545 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4546 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4547 checkFullyDefined();
4548 const double *coords=getCoords()->getConstPointer();
4549 int nbOfCells=getNumberOfCells();
4550 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4551 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4553 int *workIndexOut=nodalConnecIndexOut->getPointer();
4555 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4556 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4557 std::set<INTERP_KERNEL::NormalizedCellType> types;
4558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4559 isChanged->alloc(0,1);
4560 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4562 int pos=nodalConnecOut->getNumberOfTuples();
4563 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4564 isChanged->pushBackSilent(i);
4565 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4566 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4568 if(isChanged->empty())
4570 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4572 return isChanged.retn();
4576 * This method is \b NOT const because it can modify 'this'.
4577 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4578 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4579 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4580 * \b 1 for translation and rotation around point of 'mesh1D'.
4581 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
4583 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4585 checkFullyDefined();
4586 mesh1D->checkFullyDefined();
4587 if(!mesh1D->isContiguous1D())
4588 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4589 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4590 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4591 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4592 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4593 if(mesh1D->getMeshDimension()!=1)
4594 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4596 if(isPresenceOfQuadratic())
4598 if(mesh1D->isFullyQuadratic())
4601 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4604 int oldNbOfNodes=getNumberOfNodes();
4605 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4610 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4615 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4619 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4621 setCoords(newCoords);
4622 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4628 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4629 * If it is not the case an exception will be thrown.
4630 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4631 * intersection of plane defined by ('origin','vec').
4632 * This method has one in/out parameter : 'cut3DCurve'.
4633 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4634 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4635 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4636 * This method will throw an exception if 'this' contains a non linear segment.
4638 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4640 checkFullyDefined();
4641 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4642 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4643 int ncells=getNumberOfCells();
4644 int nnodes=getNumberOfNodes();
4645 double vec2[3],vec3[3],vec4[3];
4646 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4648 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4649 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4650 const int *conn=_nodal_connec->getConstPointer();
4651 const int *connI=_nodal_connec_index->getConstPointer();
4652 const double *coo=_coords->getConstPointer();
4653 std::vector<double> addCoo;
4654 for(int i=0;i<ncells;i++)
4656 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4658 if(cut3DCurve[i]==-2)
4660 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4661 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];
4662 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4663 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4664 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4666 const double *st2=coo+3*st;
4667 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4668 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]));
4669 if(pos>eps && pos<1-eps)
4671 int nNode=((int)addCoo.size())/3;
4672 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4673 addCoo.insert(addCoo.end(),vec4,vec4+3);
4674 cut3DCurve[i]=nnodes+nNode;
4680 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4684 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4685 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4686 coo2->alloc(newNbOfNodes,3);
4687 double *tmp=coo2->getPointer();
4688 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4689 std::copy(addCoo.begin(),addCoo.end(),tmp);
4690 DataArrayDouble::SetArrayIn(coo2,_coords);
4695 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4696 * @param mesh1D is the input 1D mesh used for translation computation.
4697 * @return newCoords new coords filled by this method.
4699 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4701 int oldNbOfNodes=getNumberOfNodes();
4702 int nbOf1DCells=mesh1D->getNumberOfCells();
4703 int spaceDim=getSpaceDimension();
4704 DataArrayDouble *ret=DataArrayDouble::New();
4705 std::vector<bool> isQuads;
4706 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4707 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4708 double *retPtr=ret->getPointer();
4709 const double *coords=getCoords()->getConstPointer();
4710 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4712 std::vector<double> c;
4716 for(int i=0;i<nbOf1DCells;i++)
4719 mesh1D->getNodeIdsOfCell(i,v);
4721 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4722 mesh1D->getCoordinatesOfNode(v[0],c);
4723 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4724 for(int j=0;j<oldNbOfNodes;j++)
4725 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4729 mesh1D->getCoordinatesOfNode(v[1],c);
4730 mesh1D->getCoordinatesOfNode(v[0],c);
4731 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4732 for(int j=0;j<oldNbOfNodes;j++)
4733 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4736 ret->copyStringInfoFrom(*getCoords());
4741 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4742 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4743 * @return newCoords new coords filled by this method.
4745 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4747 if(mesh1D->getSpaceDimension()==2)
4748 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4749 if(mesh1D->getSpaceDimension()==3)
4750 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4751 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4755 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4756 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4757 * @return newCoords new coords filled by this method.
4759 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4762 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4763 int oldNbOfNodes=getNumberOfNodes();
4764 int nbOf1DCells=mesh1D->getNumberOfCells();
4766 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4767 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4768 int nbOfLevsInVec=nbOf1DCells+1;
4769 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4770 double *retPtr=ret->getPointer();
4771 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4772 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4773 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4774 tmp->setCoords(tmp2);
4775 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4776 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4777 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4778 for(int i=1;i<nbOfLevsInVec;i++)
4780 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4781 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4782 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4783 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4784 tmp->translate(vec);
4785 double tmp3[2],radius,alpha,alpha0;
4786 const double *p0=i+1<nbOfLevsInVec?begin:third;
4787 const double *p1=i+1<nbOfLevsInVec?end:begin;
4788 const double *p2=i+1<nbOfLevsInVec?third:end;
4789 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4790 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]);
4791 double angle=acos(cosangle/(radius*radius));
4792 tmp->rotate(end,0,angle);
4793 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4799 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4800 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4801 * @return newCoords new coords filled by this method.
4803 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4806 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4807 int oldNbOfNodes=getNumberOfNodes();
4808 int nbOf1DCells=mesh1D->getNumberOfCells();
4810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4811 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4812 int nbOfLevsInVec=nbOf1DCells+1;
4813 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4814 double *retPtr=ret->getPointer();
4815 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4816 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4817 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4818 tmp->setCoords(tmp2);
4819 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4820 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4821 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4822 for(int i=1;i<nbOfLevsInVec;i++)
4824 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4825 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4826 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4827 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4828 tmp->translate(vec);
4829 double tmp3[2],radius,alpha,alpha0;
4830 const double *p0=i+1<nbOfLevsInVec?begin:third;
4831 const double *p1=i+1<nbOfLevsInVec?end:begin;
4832 const double *p2=i+1<nbOfLevsInVec?third:end;
4833 double vecPlane[3]={
4834 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4835 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4836 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4838 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4841 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4842 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4843 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4845 double c2=cos(asin(s2));
4847 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4848 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4849 {-vec2[1]*s2, vec2[0]*s2, c2}
4851 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]};
4852 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]};
4853 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]};
4854 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4855 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]);
4856 double angle=acos(cosangle/(radius*radius));
4857 tmp->rotate(end,vecPlane,angle);
4860 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4866 * This method is private because not easy to use for end user. This method is const contrary to
4867 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4868 * the coords sorted slice by slice.
4869 * @param isQuad specifies presence of quadratic cells.
4871 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4873 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4874 int nbOf2DCells=getNumberOfCells();
4875 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4876 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4877 const int *conn=_nodal_connec->getConstPointer();
4878 const int *connI=_nodal_connec_index->getConstPointer();
4879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4881 newConnI->alloc(nbOf3DCells+1,1);
4882 int *newConnIPtr=newConnI->getPointer();
4884 std::vector<int> newc;
4885 for(int j=0;j<nbOf2DCells;j++)
4887 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4888 *newConnIPtr++=(int)newc.size();
4890 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4891 int *newConnPtr=newConn->getPointer();
4892 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4893 newConnIPtr=newConnI->getPointer();
4894 for(int iz=0;iz<nbOf1DCells;iz++)
4897 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4898 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4900 int icell=(int)(iter-newc.begin());
4901 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4904 *newConnPtr=(*iter)+iz*deltaPerLev;
4909 *newConnPtr=(*iter);
4912 ret->setConnectivity(newConn,newConnI,true);
4913 ret->setCoords(getCoords());
4918 * Checks if \a this mesh is constituted by only quadratic cells.
4919 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4920 * \throw If the coordinates array is not set.
4921 * \throw If the nodal connectivity of cells is not defined.
4923 bool MEDCouplingUMesh::isFullyQuadratic() const
4925 checkFullyDefined();
4927 int nbOfCells=getNumberOfCells();
4928 for(int i=0;i<nbOfCells && ret;i++)
4930 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4931 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4932 ret=cm.isQuadratic();
4938 * Checks if \a this mesh includes any quadratic cell.
4939 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4940 * \throw If the coordinates array is not set.
4941 * \throw If the nodal connectivity of cells is not defined.
4943 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4945 checkFullyDefined();
4947 int nbOfCells=getNumberOfCells();
4948 for(int i=0;i<nbOfCells && !ret;i++)
4950 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4951 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4952 ret=cm.isQuadratic();
4958 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4959 * this mesh, it remains unchanged.
4960 * \throw If the coordinates array is not set.
4961 * \throw If the nodal connectivity of cells is not defined.
4963 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4965 checkFullyDefined();
4966 int nbOfCells=getNumberOfCells();
4968 for(int i=0;i<nbOfCells;i++)
4970 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4971 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4972 if(cm.isQuadratic())
4974 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4975 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4976 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4983 newConn->alloc(getMeshLength()-delta,1);
4984 newConnI->alloc(nbOfCells+1,1);
4985 const int *icptr=_nodal_connec->getConstPointer();
4986 const int *iciptr=_nodal_connec_index->getConstPointer();
4987 int *ocptr=newConn->getPointer();
4988 int *ociptr=newConnI->getPointer();
4991 for(int i=0;i<nbOfCells;i++,ociptr++)
4993 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4994 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4995 if(!cm.isQuadratic())
4997 _types.insert(type);
4998 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4999 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5003 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5004 _types.insert(typel);
5005 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5006 int newNbOfNodes=cml.getNumberOfNodes();
5007 *ocptr++=(int)typel;
5008 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5009 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5012 setConnectivity(newConn,newConnI,false);
5016 * This method converts all linear cell in \a this to quadratic one.
5017 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5018 * 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)
5019 * 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.
5020 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5021 * end of the existing coordinates.
5023 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5024 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5025 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5027 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5029 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5031 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
5033 DataArrayInt *conn=0,*connI=0;
5034 DataArrayDouble *coords=0;
5035 std::set<INTERP_KERNEL::NormalizedCellType> types;
5036 checkFullyDefined();
5037 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5038 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5039 int meshDim=getMeshDimension();
5040 switch(conversionType)
5046 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5047 connSafe=conn; connISafe=connI; coordsSafe=coords;
5050 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5051 connSafe=conn; connISafe=connI; coordsSafe=coords;
5054 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5055 connSafe=conn; connISafe=connI; coordsSafe=coords;
5058 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5066 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5067 connSafe=conn; connISafe=connI; coordsSafe=coords;
5070 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5071 connSafe=conn; connISafe=connI; coordsSafe=coords;
5074 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5075 connSafe=conn; connISafe=connI; coordsSafe=coords;
5078 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5083 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5085 setConnectivity(connSafe,connISafe,false);
5087 setCoords(coordsSafe);
5092 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5093 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5094 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5096 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5098 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5099 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5101 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5102 int nbOfCells=getNumberOfCells();
5103 int nbOfNodes=getNumberOfNodes();
5104 const int *cPtr=_nodal_connec->getConstPointer();
5105 const int *icPtr=_nodal_connec_index->getConstPointer();
5106 int lastVal=0,offset=nbOfNodes;
5107 for(int i=0;i<nbOfCells;i++,icPtr++)
5109 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5110 if(type==INTERP_KERNEL::NORM_SEG2)
5112 types.insert(INTERP_KERNEL::NORM_SEG3);
5113 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5114 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5115 newConn->pushBackSilent(offset++);
5117 newConnI->pushBackSilent(lastVal);
5118 ret->pushBackSilent(i);
5123 lastVal+=(icPtr[1]-icPtr[0]);
5124 newConnI->pushBackSilent(lastVal);
5125 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5128 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5129 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5133 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)
5135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5137 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5139 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5140 DataArrayInt *conn1D=0,*conn1DI=0;
5141 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5142 DataArrayDouble *coordsTmp=0;
5143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5144 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5146 const int *c1DPtr=conn1D->begin();
5147 const int *c1DIPtr=conn1DI->begin();
5148 int nbOfCells=getNumberOfCells();
5149 const int *cPtr=_nodal_connec->getConstPointer();
5150 const int *icPtr=_nodal_connec_index->getConstPointer();
5152 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5154 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5155 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5156 if(!cm.isQuadratic())
5158 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5159 types.insert(typ2); newConn->pushBackSilent(typ2);
5160 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5161 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5162 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5163 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5164 newConnI->pushBackSilent(lastVal);
5165 ret->pushBackSilent(i);
5170 lastVal+=(icPtr[1]-icPtr[0]);
5171 newConnI->pushBackSilent(lastVal);
5172 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5175 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5180 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5181 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5182 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5184 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5188 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5189 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5192 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5195 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5202 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5203 DataArrayInt *conn1D=0,*conn1DI=0;
5204 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5205 DataArrayDouble *coordsTmp=0;
5206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5207 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5209 const int *c1DPtr=conn1D->begin();
5210 const int *c1DIPtr=conn1DI->begin();
5211 int nbOfCells=getNumberOfCells();
5212 const int *cPtr=_nodal_connec->getConstPointer();
5213 const int *icPtr=_nodal_connec_index->getConstPointer();
5214 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5215 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5217 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5218 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5219 if(!cm.isQuadratic())
5221 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5222 types.insert(typ2); newConn->pushBackSilent(typ2);
5223 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5224 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5225 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5226 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5227 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5228 newConnI->pushBackSilent(lastVal);
5229 ret->pushBackSilent(i);
5234 lastVal+=(icPtr[1]-icPtr[0]);
5235 newConnI->pushBackSilent(lastVal);
5236 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5239 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5240 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5245 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5246 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5247 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5249 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5252 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5253 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5256 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5259 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5261 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5264 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5267 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5268 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5269 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5270 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5271 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5274 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5278 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5279 int nbOfCells=getNumberOfCells();
5280 const int *cPtr=_nodal_connec->getConstPointer();
5281 const int *icPtr=_nodal_connec_index->getConstPointer();
5282 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5283 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5285 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5286 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5287 if(!cm.isQuadratic())
5289 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5290 if(typ2==INTERP_KERNEL::NORM_ERROR)
5292 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5293 throw INTERP_KERNEL::Exception(oss.str().c_str());
5295 types.insert(typ2); newConn->pushBackSilent(typ2);
5296 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5297 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5298 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5299 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5301 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5302 int tmpPos=newConn->getNumberOfTuples();
5303 newConn->pushBackSilent(nodeId2);
5304 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5306 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5307 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5308 newConnI->pushBackSilent(lastVal);
5309 ret->pushBackSilent(i);
5314 lastVal+=(icPtr[1]-icPtr[0]);
5315 newConnI->pushBackSilent(lastVal);
5316 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5321 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5322 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5323 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5324 int *c=newConn->getPointer();
5325 const int *cI(newConnI->begin());
5326 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5327 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5328 offset=coordsTmp2Safe->getNumberOfTuples();
5329 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5330 c[cI[(*elt)+1]-1]+=offset;
5331 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5336 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5337 * so that the number of cells remains the same. Quadratic faces are converted to
5338 * polygons. This method works only for 2D meshes in
5339 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5340 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5341 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5342 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5343 * a polylinized edge constituting the input polygon.
5344 * \throw If the coordinates array is not set.
5345 * \throw If the nodal connectivity of cells is not defined.
5346 * \throw If \a this->getMeshDimension() != 2.
5347 * \throw If \a this->getSpaceDimension() != 2.
5349 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5351 checkFullyDefined();
5352 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5354 double epsa=fabs(eps);
5355 if(epsa<std::numeric_limits<double>::min())
5356 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 !");
5357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5361 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5362 revDesc1=0; revDescIndx1=0;
5363 mDesc->tessellate2DCurve(eps);
5364 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5365 setCoords(mDesc->getCoords());
5369 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5370 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5371 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5372 * a sub-divided edge.
5373 * \throw If the coordinates array is not set.
5374 * \throw If the nodal connectivity of cells is not defined.
5375 * \throw If \a this->getMeshDimension() != 1.
5376 * \throw If \a this->getSpaceDimension() != 2.
5378 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5380 checkFullyDefined();
5381 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5382 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5383 double epsa=fabs(eps);
5384 if(epsa<std::numeric_limits<double>::min())
5385 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 !");
5386 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5387 int nbCells=getNumberOfCells();
5388 int nbNodes=getNumberOfNodes();
5389 const int *conn=_nodal_connec->getConstPointer();
5390 const int *connI=_nodal_connec_index->getConstPointer();
5391 const double *coords=_coords->getConstPointer();
5392 std::vector<double> addCoo;
5393 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5395 newConnI->alloc(nbCells+1,1);
5396 int *newConnIPtr=newConnI->getPointer();
5399 INTERP_KERNEL::Node *tmp2[3];
5400 std::set<INTERP_KERNEL::NormalizedCellType> types;
5401 for(int i=0;i<nbCells;i++,newConnIPtr++)
5403 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5404 if(cm.isQuadratic())
5405 {//assert(connI[i+1]-connI[i]-1==3)
5406 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5407 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5408 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5409 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5410 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5413 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5414 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5416 newConnIPtr[1]=(int)newConn.size();
5420 types.insert(INTERP_KERNEL::NORM_SEG2);
5421 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5422 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5423 newConnIPtr[1]=newConnIPtr[0]+3;
5428 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5429 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5430 newConnIPtr[1]=newConnIPtr[0]+3;
5433 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5436 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5438 newConnArr->alloc((int)newConn.size(),1);
5439 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5440 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5441 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5442 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5443 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5444 std::copy(addCoo.begin(),addCoo.end(),work);
5445 DataArrayDouble::SetArrayIn(newCoords,_coords);
5450 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5451 * In addition, returns an array mapping new cells to old ones. <br>
5452 * This method typically increases the number of cells in \a this mesh
5453 * but the number of nodes remains \b unchanged.
5454 * That's why the 3D splitting policies
5455 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5456 * \param [in] policy - specifies a pattern used for splitting.
5457 * The semantic of \a policy is:
5458 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5459 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5460 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5461 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5462 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5463 * an id of old cell producing it. The caller is to delete this array using
5464 * decrRef() as it is no more needed.
5465 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5466 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5467 * and \a this->getMeshDimension() != 3.
5468 * \throw If \a policy is not one of the four discussed above.
5469 * \throw If the nodal connectivity of cells is not defined.
5471 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5476 return simplexizePol0();
5478 return simplexizePol1();
5479 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5480 return simplexizePlanarFace5();
5481 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5482 return simplexizePlanarFace6();
5484 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)");
5489 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5490 * - 1D: INTERP_KERNEL::NORM_SEG2
5491 * - 2D: INTERP_KERNEL::NORM_TRI3
5492 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5494 * This method is useful for users that need to use P1 field services as
5495 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5496 * All these methods need mesh support containing only simplex cells.
5497 * \return bool - \c true if there are only simplex cells in \a this mesh.
5498 * \throw If the coordinates array is not set.
5499 * \throw If the nodal connectivity of cells is not defined.
5500 * \throw If \a this->getMeshDimension() < 1.
5502 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5504 checkFullyDefined();
5505 int mdim=getMeshDimension();
5506 if(mdim<1 || mdim>3)
5507 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5508 int nbCells=getNumberOfCells();
5509 const int *conn=_nodal_connec->getConstPointer();
5510 const int *connI=_nodal_connec_index->getConstPointer();
5511 for(int i=0;i<nbCells;i++)
5513 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5521 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5523 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5525 checkConnectivityFullyDefined();
5526 if(getMeshDimension()!=2)
5527 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5528 int nbOfCells=getNumberOfCells();
5529 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5530 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5531 ret->alloc(nbOfCells+nbOfCutCells,1);
5532 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5533 int *retPt=ret->getPointer();
5534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5535 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5536 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5537 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5538 int *pt=newConn->getPointer();
5539 int *ptI=newConnI->getPointer();
5541 const int *oldc=_nodal_connec->getConstPointer();
5542 const int *ci=_nodal_connec_index->getConstPointer();
5543 for(int i=0;i<nbOfCells;i++,ci++)
5545 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5547 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5548 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5549 pt=std::copy(tmp,tmp+8,pt);
5558 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5559 ptI[1]=ptI[0]+ci[1]-ci[0];
5564 _nodal_connec->decrRef();
5565 _nodal_connec=newConn.retn();
5566 _nodal_connec_index->decrRef();
5567 _nodal_connec_index=newConnI.retn();
5574 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5576 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5578 checkConnectivityFullyDefined();
5579 if(getMeshDimension()!=2)
5580 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5581 int nbOfCells=getNumberOfCells();
5582 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5583 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5584 ret->alloc(nbOfCells+nbOfCutCells,1);
5585 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5586 int *retPt=ret->getPointer();
5587 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5589 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5590 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5591 int *pt=newConn->getPointer();
5592 int *ptI=newConnI->getPointer();
5594 const int *oldc=_nodal_connec->getConstPointer();
5595 const int *ci=_nodal_connec_index->getConstPointer();
5596 for(int i=0;i<nbOfCells;i++,ci++)
5598 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5600 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5601 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5602 pt=std::copy(tmp,tmp+8,pt);
5611 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5612 ptI[1]=ptI[0]+ci[1]-ci[0];
5617 _nodal_connec->decrRef();
5618 _nodal_connec=newConn.retn();
5619 _nodal_connec_index->decrRef();
5620 _nodal_connec_index=newConnI.retn();
5627 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5629 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5631 checkConnectivityFullyDefined();
5632 if(getMeshDimension()!=3)
5633 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5634 int nbOfCells=getNumberOfCells();
5635 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5636 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5637 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5638 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5639 int *retPt=ret->getPointer();
5640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5642 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5643 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5644 int *pt=newConn->getPointer();
5645 int *ptI=newConnI->getPointer();
5647 const int *oldc=_nodal_connec->getConstPointer();
5648 const int *ci=_nodal_connec_index->getConstPointer();
5649 for(int i=0;i<nbOfCells;i++,ci++)
5651 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5653 for(int j=0;j<5;j++,pt+=5,ptI++)
5655 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5656 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];
5663 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5664 ptI[1]=ptI[0]+ci[1]-ci[0];
5669 _nodal_connec->decrRef();
5670 _nodal_connec=newConn.retn();
5671 _nodal_connec_index->decrRef();
5672 _nodal_connec_index=newConnI.retn();
5679 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5681 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5683 checkConnectivityFullyDefined();
5684 if(getMeshDimension()!=3)
5685 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5686 int nbOfCells=getNumberOfCells();
5687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5688 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5689 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5690 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5691 int *retPt=ret->getPointer();
5692 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5693 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5694 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5695 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5696 int *pt=newConn->getPointer();
5697 int *ptI=newConnI->getPointer();
5699 const int *oldc=_nodal_connec->getConstPointer();
5700 const int *ci=_nodal_connec_index->getConstPointer();
5701 for(int i=0;i<nbOfCells;i++,ci++)
5703 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5705 for(int j=0;j<6;j++,pt+=5,ptI++)
5707 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5708 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];
5715 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5716 ptI[1]=ptI[0]+ci[1]-ci[0];
5721 _nodal_connec->decrRef();
5722 _nodal_connec=newConn.retn();
5723 _nodal_connec_index->decrRef();
5724 _nodal_connec_index=newConnI.retn();
5731 * This private method is used to subdivide edges of a mesh with meshdim==2. If 'this' has no a meshdim equal to 2 an exception will be thrown.
5732 * This method completly ignore coordinates.
5733 * @param nodeSubdived is the nodal connectivity of subdivision of edges
5734 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5735 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5736 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5738 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5740 checkFullyDefined();
5741 if(getMeshDimension()!=2)
5742 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5743 int nbOfCells=getNumberOfCells();
5744 int *connI=_nodal_connec_index->getPointer();
5746 for(int i=0;i<nbOfCells;i++,connI++)
5748 int offset=descIndex[i];
5749 int nbOfEdges=descIndex[i+1]-offset;
5751 bool ddirect=desc[offset+nbOfEdges-1]>0;
5752 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5753 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5754 for(int j=0;j<nbOfEdges;j++)
5756 bool direct=desc[offset+j]>0;
5757 int edgeId=std::abs(desc[offset+j])-1;
5758 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5760 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5761 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5762 int ref2=direct?id1:id2;
5765 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5766 newConnLgth+=nbOfSubNodes-1;
5771 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5772 throw INTERP_KERNEL::Exception(oss.str().c_str());
5777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5780 newConnLgth++;//+1 is for cell type
5781 connI[1]=newConnLgth;
5784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5785 newConn->alloc(newConnLgth,1);
5786 int *work=newConn->getPointer();
5787 for(int i=0;i<nbOfCells;i++)
5789 *work++=INTERP_KERNEL::NORM_POLYGON;
5790 int offset=descIndex[i];
5791 int nbOfEdges=descIndex[i+1]-offset;
5792 for(int j=0;j<nbOfEdges;j++)
5794 bool direct=desc[offset+j]>0;
5795 int edgeId=std::abs(desc[offset+j])-1;
5797 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5800 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5801 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5802 work=std::copy(it,it+nbOfSubNodes-1,work);
5806 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5809 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5813 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5814 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5815 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5816 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5817 * so it can be useful to call mergeNodes() before calling this method.
5818 * \throw If \a this->getMeshDimension() <= 1.
5819 * \throw If the coordinates array is not set.
5820 * \throw If the nodal connectivity of cells is not defined.
5822 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5824 checkFullyDefined();
5825 if(getMeshDimension()<=1)
5826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5827 int nbOfCells=getNumberOfCells();
5830 int initMeshLgth=getMeshLength();
5831 int *conn=_nodal_connec->getPointer();
5832 int *index=_nodal_connec_index->getPointer();
5836 for(int i=0;i<nbOfCells;i++)
5838 lgthOfCurCell=index[i+1]-posOfCurCell;
5839 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5841 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5842 conn+newPos+1,newLgth);
5843 conn[newPos]=newType;
5845 posOfCurCell=index[i+1];
5848 if(newPos!=initMeshLgth)
5849 _nodal_connec->reAlloc(newPos);
5854 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5855 * A cell is considered to be oriented correctly if an angle between its
5856 * normal vector and a given vector is less than \c PI / \c 2.
5857 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5859 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5861 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5862 * is not cleared before filling in.
5863 * \throw If \a this->getMeshDimension() != 2.
5864 * \throw If \a this->getSpaceDimension() != 3.
5866 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5867 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5869 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5871 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5872 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5873 int nbOfCells=getNumberOfCells();
5874 const int *conn=_nodal_connec->getConstPointer();
5875 const int *connI=_nodal_connec_index->getConstPointer();
5876 const double *coordsPtr=_coords->getConstPointer();
5877 for(int i=0;i<nbOfCells;i++)
5879 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5880 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5882 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5883 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5890 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5891 * considered to be oriented correctly if an angle between its normal vector and a
5892 * given vector is less than \c PI / \c 2.
5893 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5895 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5897 * \throw If \a this->getMeshDimension() != 2.
5898 * \throw If \a this->getSpaceDimension() != 3.
5900 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5901 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5903 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5905 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5906 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5907 int nbOfCells=getNumberOfCells();
5908 int *conn=_nodal_connec->getPointer();
5909 const int *connI=_nodal_connec_index->getConstPointer();
5910 const double *coordsPtr=_coords->getConstPointer();
5911 bool isModified=false;
5912 for(int i=0;i<nbOfCells;i++)
5914 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5915 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5917 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5918 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5921 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5922 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5923 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5928 _nodal_connec->declareAsNew();
5933 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5934 * oriented facets. The normal vector of the facet should point out of the cell.
5935 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5936 * is not cleared before filling in.
5937 * \throw If \a this->getMeshDimension() != 3.
5938 * \throw If \a this->getSpaceDimension() != 3.
5939 * \throw If the coordinates array is not set.
5940 * \throw If the nodal connectivity of cells is not defined.
5942 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5943 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5945 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5947 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5948 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5949 int nbOfCells=getNumberOfCells();
5950 const int *conn=_nodal_connec->getConstPointer();
5951 const int *connI=_nodal_connec_index->getConstPointer();
5952 const double *coordsPtr=_coords->getConstPointer();
5953 for(int i=0;i<nbOfCells;i++)
5955 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5956 if(type==INTERP_KERNEL::NORM_POLYHED)
5958 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5965 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5967 * \throw If \a this->getMeshDimension() != 3.
5968 * \throw If \a this->getSpaceDimension() != 3.
5969 * \throw If the coordinates array is not set.
5970 * \throw If the nodal connectivity of cells is not defined.
5971 * \throw If the reparation fails.
5973 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5974 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5975 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5977 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5979 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5980 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5981 int nbOfCells=getNumberOfCells();
5982 int *conn=_nodal_connec->getPointer();
5983 const int *connI=_nodal_connec_index->getConstPointer();
5984 const double *coordsPtr=_coords->getConstPointer();
5985 for(int i=0;i<nbOfCells;i++)
5987 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5988 if(type==INTERP_KERNEL::NORM_POLYHED)
5992 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5993 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5995 catch(INTERP_KERNEL::Exception& e)
5997 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5998 throw INTERP_KERNEL::Exception(oss.str().c_str());
6006 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6007 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6008 * according to which the first facet of the cell should be oriented to have the normal vector
6009 * pointing out of cell.
6010 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6011 * cells. The caller is to delete this array using decrRef() as it is no more
6013 * \throw If \a this->getMeshDimension() != 3.
6014 * \throw If \a this->getSpaceDimension() != 3.
6015 * \throw If the coordinates array is not set.
6016 * \throw If the nodal connectivity of cells is not defined.
6018 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6019 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6020 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6022 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
6024 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6025 if(getMeshDimension()!=3)
6026 throw INTERP_KERNEL::Exception(msg);
6027 int spaceDim=getSpaceDimension();
6029 throw INTERP_KERNEL::Exception(msg);
6031 int nbOfCells=getNumberOfCells();
6032 int *conn=_nodal_connec->getPointer();
6033 const int *connI=_nodal_connec_index->getConstPointer();
6034 const double *coo=getCoords()->getConstPointer();
6035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6036 for(int i=0;i<nbOfCells;i++)
6038 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6039 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6041 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6043 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6044 cells->pushBackSilent(i);
6048 return cells.retn();
6052 * This method is a faster method to correct orientation of all 3D cells in \a this.
6053 * 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.
6054 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6056 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6057 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6059 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
6061 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6062 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6063 int nbOfCells=getNumberOfCells();
6064 int *conn=_nodal_connec->getPointer();
6065 const int *connI=_nodal_connec_index->getConstPointer();
6066 const double *coordsPtr=_coords->getConstPointer();
6067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6068 for(int i=0;i<nbOfCells;i++)
6070 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6073 case INTERP_KERNEL::NORM_TETRA4:
6075 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6077 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6078 ret->pushBackSilent(i);
6082 case INTERP_KERNEL::NORM_PYRA5:
6084 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6086 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6087 ret->pushBackSilent(i);
6091 case INTERP_KERNEL::NORM_PENTA6:
6092 case INTERP_KERNEL::NORM_HEXA8:
6093 case INTERP_KERNEL::NORM_HEXGP12:
6095 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6097 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6098 ret->pushBackSilent(i);
6102 case INTERP_KERNEL::NORM_POLYHED:
6104 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6106 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6107 ret->pushBackSilent(i);
6112 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 !");
6120 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6121 * If it is not the case an exception will be thrown.
6122 * This method is fast because the first cell of 'this' is used to compute the plane.
6123 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6124 * @param pos output of size at least 3 used to store a point owned of searched plane.
6126 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
6128 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6129 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6130 const int *conn=_nodal_connec->getConstPointer();
6131 const int *connI=_nodal_connec_index->getConstPointer();
6132 const double *coordsPtr=_coords->getConstPointer();
6133 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6134 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6138 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6139 * cells. Currently cells of the following types are treated:
6140 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6141 * For a cell of other type an exception is thrown.
6142 * Space dimension of a 2D mesh can be either 2 or 3.
6143 * The Edge Ratio of a cell \f$t\f$ is:
6144 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6145 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6146 * the smallest edge lengths of \f$t\f$.
6147 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6148 * cells and one time, lying on \a this mesh. The caller is to delete this
6149 * field using decrRef() as it is no more needed.
6150 * \throw If the coordinates array is not set.
6151 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6152 * \throw If the connectivity data array has more than one component.
6153 * \throw If the connectivity data array has a named component.
6154 * \throw If the connectivity index data array has more than one component.
6155 * \throw If the connectivity index data array has a named component.
6156 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6157 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6158 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6160 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
6163 int spaceDim=getSpaceDimension();
6164 int meshDim=getMeshDimension();
6165 if(spaceDim!=2 && spaceDim!=3)
6166 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6167 if(meshDim!=2 && meshDim!=3)
6168 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6169 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6171 int nbOfCells=getNumberOfCells();
6172 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6173 arr->alloc(nbOfCells,1);
6174 double *pt=arr->getPointer();
6175 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6176 const int *conn=_nodal_connec->getConstPointer();
6177 const int *connI=_nodal_connec_index->getConstPointer();
6178 const double *coo=_coords->getConstPointer();
6180 for(int i=0;i<nbOfCells;i++,pt++)
6182 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6185 case INTERP_KERNEL::NORM_TRI3:
6187 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6188 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6191 case INTERP_KERNEL::NORM_QUAD4:
6193 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6194 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6197 case INTERP_KERNEL::NORM_TETRA4:
6199 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6200 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6204 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6206 conn+=connI[i+1]-connI[i];
6208 ret->setName("EdgeRatio");
6209 ret->synchronizeTimeWithSupport();
6214 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6215 * cells. Currently cells of the following types are treated:
6216 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6217 * For a cell of other type an exception is thrown.
6218 * Space dimension of a 2D mesh can be either 2 or 3.
6219 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6220 * cells and one time, lying on \a this mesh. The caller is to delete this
6221 * field using decrRef() as it is no more needed.
6222 * \throw If the coordinates array is not set.
6223 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6224 * \throw If the connectivity data array has more than one component.
6225 * \throw If the connectivity data array has a named component.
6226 * \throw If the connectivity index data array has more than one component.
6227 * \throw If the connectivity index data array has a named component.
6228 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6229 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6230 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6232 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6235 int spaceDim=getSpaceDimension();
6236 int meshDim=getMeshDimension();
6237 if(spaceDim!=2 && spaceDim!=3)
6238 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6239 if(meshDim!=2 && meshDim!=3)
6240 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6241 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6243 int nbOfCells=getNumberOfCells();
6244 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6245 arr->alloc(nbOfCells,1);
6246 double *pt=arr->getPointer();
6247 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6248 const int *conn=_nodal_connec->getConstPointer();
6249 const int *connI=_nodal_connec_index->getConstPointer();
6250 const double *coo=_coords->getConstPointer();
6252 for(int i=0;i<nbOfCells;i++,pt++)
6254 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6257 case INTERP_KERNEL::NORM_TRI3:
6259 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6260 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6263 case INTERP_KERNEL::NORM_QUAD4:
6265 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6266 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6269 case INTERP_KERNEL::NORM_TETRA4:
6271 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6272 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6278 conn+=connI[i+1]-connI[i];
6280 ret->setName("AspectRatio");
6281 ret->synchronizeTimeWithSupport();
6286 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6287 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6288 * treated: INTERP_KERNEL::NORM_QUAD4.
6289 * For a cell of other type an exception is thrown.
6290 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6291 * cells and one time, lying on \a this mesh. The caller is to delete this
6292 * field using decrRef() as it is no more needed.
6293 * \throw If the coordinates array is not set.
6294 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6295 * \throw If the connectivity data array has more than one component.
6296 * \throw If the connectivity data array has a named component.
6297 * \throw If the connectivity index data array has more than one component.
6298 * \throw If the connectivity index data array has a named component.
6299 * \throw If \a this->getMeshDimension() != 2.
6300 * \throw If \a this->getSpaceDimension() != 3.
6301 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6303 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6306 int spaceDim=getSpaceDimension();
6307 int meshDim=getMeshDimension();
6309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6311 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6312 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6314 int nbOfCells=getNumberOfCells();
6315 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6316 arr->alloc(nbOfCells,1);
6317 double *pt=arr->getPointer();
6318 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6319 const int *conn=_nodal_connec->getConstPointer();
6320 const int *connI=_nodal_connec_index->getConstPointer();
6321 const double *coo=_coords->getConstPointer();
6323 for(int i=0;i<nbOfCells;i++,pt++)
6325 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6328 case INTERP_KERNEL::NORM_QUAD4:
6330 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6331 *pt=INTERP_KERNEL::quadWarp(tmp);
6335 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6337 conn+=connI[i+1]-connI[i];
6339 ret->setName("Warp");
6340 ret->synchronizeTimeWithSupport();
6346 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6347 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6348 * treated: INTERP_KERNEL::NORM_QUAD4.
6349 * For a cell of other type an exception is thrown.
6350 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6351 * cells and one time, lying on \a this mesh. The caller is to delete this
6352 * field using decrRef() as it is no more needed.
6353 * \throw If the coordinates array is not set.
6354 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6355 * \throw If the connectivity data array has more than one component.
6356 * \throw If the connectivity data array has a named component.
6357 * \throw If the connectivity index data array has more than one component.
6358 * \throw If the connectivity index data array has a named component.
6359 * \throw If \a this->getMeshDimension() != 2.
6360 * \throw If \a this->getSpaceDimension() != 3.
6361 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6363 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6366 int spaceDim=getSpaceDimension();
6367 int meshDim=getMeshDimension();
6369 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6372 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6374 int nbOfCells=getNumberOfCells();
6375 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6376 arr->alloc(nbOfCells,1);
6377 double *pt=arr->getPointer();
6378 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6379 const int *conn=_nodal_connec->getConstPointer();
6380 const int *connI=_nodal_connec_index->getConstPointer();
6381 const double *coo=_coords->getConstPointer();
6383 for(int i=0;i<nbOfCells;i++,pt++)
6385 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6388 case INTERP_KERNEL::NORM_QUAD4:
6390 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6391 *pt=INTERP_KERNEL::quadSkew(tmp);
6395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6397 conn+=connI[i+1]-connI[i];
6399 ret->setName("Skew");
6400 ret->synchronizeTimeWithSupport();
6405 * This method aggregate the bbox of each cell and put it into bbox parameter.
6406 * @param bbox out parameter of size 2*spacedim*nbOfcells.
6408 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6410 int spaceDim=getSpaceDimension();
6411 int nbOfCells=getNumberOfCells();
6412 bbox.resize(2*nbOfCells*spaceDim);
6413 for(int i=0;i<nbOfCells*spaceDim;i++)
6415 bbox[2*i]=std::numeric_limits<double>::max();
6416 bbox[2*i+1]=-std::numeric_limits<double>::max();
6418 const double *coordsPtr=_coords->getConstPointer();
6419 const int *conn=_nodal_connec->getConstPointer();
6420 const int *connI=_nodal_connec_index->getConstPointer();
6421 for(int i=0;i<nbOfCells;i++)
6423 int offset=connI[i]+1;
6424 int nbOfNodesForCell=connI[i+1]-offset;
6425 for(int j=0;j<nbOfNodesForCell;j++)
6427 int nodeId=conn[offset+j];
6429 for(int k=0;k<spaceDim;k++)
6431 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6432 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6440 namespace ParaMEDMEMImpl
6445 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6446 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6455 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6456 bool operator() (const int& pos) { return _conn[pos]==_val; }
6466 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
6467 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6468 * 'this' is composed in cell types.
6469 * The returned array is of size 3*n where n is the number of different types present in 'this'.
6470 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
6471 * This parameter is kept only for compatibility with other methode listed above.
6473 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6475 checkConnectivityFullyDefined();
6476 const int *conn=_nodal_connec->getConstPointer();
6477 const int *connI=_nodal_connec_index->getConstPointer();
6478 const int *work=connI;
6479 int nbOfCells=getNumberOfCells();
6480 std::size_t n=getAllTypes().size();
6481 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6482 std::set<INTERP_KERNEL::NormalizedCellType> types;
6483 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6485 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6486 if(types.find(typ)!=types.end())
6488 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6489 oss << " is not contiguous !";
6490 throw INTERP_KERNEL::Exception(oss.str().c_str());
6494 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6495 ret[3*i+1]=(int)std::distance(work,work2);
6502 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
6503 * only for types cell, type node is not managed.
6504 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
6505 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6506 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6507 * If 2 or more same geometric type is in 'code' and exception is thrown too.
6509 * This method firstly checks
6510 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6511 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6512 * an exception is thrown too.
6514 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
6515 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
6516 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6518 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6522 std::size_t sz=code.size();
6525 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6526 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6528 for(std::size_t i=0;i<n;i++)
6529 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6531 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6533 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6534 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6537 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6538 if(idsPerType.empty())
6540 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6541 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6542 if(types.size()==_types.size())
6545 DataArrayInt *ret=DataArrayInt::New();
6547 int *retPtr=ret->getPointer();
6548 const int *connI=_nodal_connec_index->getConstPointer();
6549 const int *conn=_nodal_connec->getConstPointer();
6550 int nbOfCells=getNumberOfCells();
6553 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6555 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6556 int offset=(int)std::distance(connI,i);
6557 if(code[3*kk+2]==-1)
6559 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6560 std::size_t pos2=std::distance(i,j);
6561 for(std::size_t k=0;k<pos2;k++)
6562 *retPtr++=(int)k+offset;
6567 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6568 retPtr,std::bind2nd(std::plus<int>(),offset));
6575 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6576 * 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.
6577 * 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.
6578 * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
6580 * @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.
6581 * @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,
6582 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6583 * @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.
6584 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6585 * @throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
6587 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6589 if(profile->getNumberOfComponents()!=1)
6590 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6591 checkConnectivityFullyDefined();
6592 const int *conn=_nodal_connec->getConstPointer();
6593 const int *connI=_nodal_connec_index->getConstPointer();
6594 int nbOfCells=getNumberOfCells();
6595 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6596 std::vector<int> typeRangeVals(1);
6597 for(const int *i=connI;i!=connI+nbOfCells;)
6599 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6600 if(std::find(types.begin(),types.end(),curType)!=types.end())
6602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6604 types.push_back(curType);
6605 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6606 typeRangeVals.push_back((int)std::distance(connI,i));
6609 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6610 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6613 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6615 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6616 code.resize(3*nbOfCastsFinal);
6617 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6618 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6619 for(int i=0;i<nbOfCastsFinal;i++)
6621 int castId=castsPresent->getIJ(i,0);
6622 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6623 idsInPflPerType2.push_back(tmp3);
6624 code[3*i]=(int)types[castId];
6625 code[3*i+1]=tmp3->getNumberOfTuples();
6626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6627 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6629 tmp4->copyStringInfoFrom(*profile);
6630 idsPerType2.push_back(tmp4);
6631 code[3*i+2]=(int)idsPerType2.size()-1;
6638 std::size_t sz2=idsInPflPerType2.size();
6639 idsInPflPerType.resize(sz2);
6640 for(std::size_t i=0;i<sz2;i++)
6642 DataArrayInt *locDa=idsInPflPerType2[i];
6644 idsInPflPerType[i]=locDa;
6646 std::size_t sz=idsPerType2.size();
6647 idsPerType.resize(sz);
6648 for(std::size_t i=0;i<sz;i++)
6650 DataArrayInt *locDa=idsPerType2[i];
6652 idsPerType[i]=locDa;
6657 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6658 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6659 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6660 * 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.
6662 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6664 checkFullyDefined();
6665 nM1LevMesh->checkFullyDefined();
6666 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6667 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6668 if(_coords!=nM1LevMesh->getCoords())
6669 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6671 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6672 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6673 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6674 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6675 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6676 tmp->setConnectivity(tmp0,tmp1);
6677 tmp->renumberCells(ret0->getConstPointer(),false);
6678 revDesc=tmp->getNodalConnectivity();
6679 revDescIndx=tmp->getNodalConnectivityIndex();
6680 DataArrayInt *ret=0;
6681 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6684 ret->getMaxValue(tmp2);
6686 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6687 throw INTERP_KERNEL::Exception(oss.str().c_str());
6692 revDescIndx->incrRef();
6695 meshnM1Old2New=ret0;
6700 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6701 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6702 * in "Old to New" mode.
6703 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6704 * this array using decrRef() as it is no more needed.
6705 * \throw If the nodal connectivity of cells is not defined.
6707 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6709 checkConnectivityFullyDefined();
6710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6711 renumberCells(ret->getConstPointer(),false);
6716 * This methods checks that cells are sorted by their types.
6717 * This method makes asumption (no check) that connectivity is correctly set before calling.
6719 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6721 checkFullyDefined();
6722 const int *conn=_nodal_connec->getConstPointer();
6723 const int *connI=_nodal_connec_index->getConstPointer();
6724 int nbOfCells=getNumberOfCells();
6725 std::set<INTERP_KERNEL::NormalizedCellType> types;
6726 for(const int *i=connI;i!=connI+nbOfCells;)
6728 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6729 if(types.find(curType)!=types.end())
6731 types.insert(curType);
6732 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6738 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6739 * The geometric type order is specified by MED file.
6741 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6743 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6745 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6749 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6750 * that the order is specified in array defined by [orderBg,orderEnd).
6751 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6752 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6754 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6756 checkFullyDefined();
6757 const int *conn=_nodal_connec->getConstPointer();
6758 const int *connI=_nodal_connec_index->getConstPointer();
6759 int nbOfCells=getNumberOfCells();
6763 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6764 for(const int *i=connI;i!=connI+nbOfCells;)
6766 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6767 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6768 if(isTypeExists!=orderEnd)
6770 int pos=(int)std::distance(orderBg,isTypeExists);
6774 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6778 if(sg.find(curType)==sg.end())
6780 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6791 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6792 * 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
6793 * 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'.
6795 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6797 checkConnectivityFullyDefined();
6798 int nbOfCells=getNumberOfCells();
6799 const int *conn=_nodal_connec->getConstPointer();
6800 const int *connI=_nodal_connec_index->getConstPointer();
6801 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6802 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6803 tmpa->alloc(nbOfCells,1);
6804 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6805 tmpb->fillWithZero();
6806 int *tmp=tmpa->getPointer();
6807 int *tmp2=tmpb->getPointer();
6808 for(const int *i=connI;i!=connI+nbOfCells;i++)
6810 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6813 int pos=(int)std::distance(orderBg,where);
6815 tmp[std::distance(connI,i)]=pos;
6819 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6820 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6821 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6822 throw INTERP_KERNEL::Exception(oss.str().c_str());
6825 nbPerType=tmpb.retn();
6830 * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [orderBg,orderEnd) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in 'this'.
6831 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6832 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6833 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6835 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6837 DataArrayInt *nbPerType=0;
6838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6839 nbPerType->decrRef();
6840 return tmpa->buildPermArrPerLevel();
6844 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6845 * The number of cells remains unchanged after the call of this method.
6846 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6847 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6849 * @return the array giving the correspondance old to new.
6851 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6853 checkFullyDefined();
6855 const int *conn=_nodal_connec->getConstPointer();
6856 const int *connI=_nodal_connec_index->getConstPointer();
6857 int nbOfCells=getNumberOfCells();
6858 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6859 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6860 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6862 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6863 types.push_back(curType);
6864 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6866 DataArrayInt *ret=DataArrayInt::New();
6867 ret->alloc(nbOfCells,1);
6868 int *retPtr=ret->getPointer();
6869 std::fill(retPtr,retPtr+nbOfCells,-1);
6871 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6873 for(const int *i=connI;i!=connI+nbOfCells;i++)
6874 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6875 retPtr[std::distance(connI,i)]=newCellId++;
6877 renumberCells(retPtr,false);
6882 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6883 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6884 * This method makes asumption that connectivity is correctly set before calling.
6886 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6888 checkFullyDefined();
6889 const int *conn=_nodal_connec->getConstPointer();
6890 const int *connI=_nodal_connec_index->getConstPointer();
6891 int nbOfCells=getNumberOfCells();
6892 std::vector<MEDCouplingUMesh *> ret;
6893 for(const int *i=connI;i!=connI+nbOfCells;)
6895 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6896 int beginCellId=(int)std::distance(connI,i);
6897 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6898 int endCellId=(int)std::distance(connI,i);
6899 int sz=endCellId-beginCellId;
6900 int *cells=new int[sz];
6901 for(int j=0;j<sz;j++)
6902 cells[j]=beginCellId+j;
6903 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6911 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6912 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6913 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6914 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6915 * are not used here to avoid the build of big permutation array.
6917 * \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
6918 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6919 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6920 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6921 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6922 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6923 * \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
6924 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6926 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6927 DataArrayInt *&szOfCellGrpOfSameType,
6928 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6930 std::vector<const MEDCouplingUMesh *> ms2;
6931 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6934 (*it)->checkConnectivityFullyDefined();
6938 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6939 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6940 int meshDim=ms2[0]->getMeshDimension();
6941 std::vector<const MEDCouplingUMesh *> m1ssm;
6942 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6944 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6945 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6948 ret1->alloc(0,1); ret2->alloc(0,1);
6949 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6951 if(meshDim!=(*it)->getMeshDimension())
6952 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6953 if(refCoo!=(*it)->getCoords())
6954 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6955 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6956 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6957 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6958 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6960 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6961 m1ssmSingleAuto.push_back(singleCell);
6962 m1ssmSingle.push_back(singleCell);
6963 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6966 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6967 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6968 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6969 for(std::size_t i=0;i<m1ssm.size();i++)
6970 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6971 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6972 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6973 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6978 * This method returns a newly created DataArrayInt instance.
6979 * This method retrieves cell ids in [begin,end) that have the type 'type'.
6981 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6983 checkFullyDefined();
6984 const int *conn=_nodal_connec->getConstPointer();
6985 const int *connIndex=_nodal_connec_index->getConstPointer();
6986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6987 for(const int *w=begin;w!=end;w++)
6988 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6989 ret->pushBackSilent(*w);
6994 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6995 * are in [0:getNumberOfCells())
6997 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6999 checkFullyDefined();
7000 const int *conn=_nodal_connec->getConstPointer();
7001 const int *connI=_nodal_connec_index->getConstPointer();
7002 int nbOfCells=getNumberOfCells();
7003 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
7004 int *tmp=new int[nbOfCells];
7005 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7008 for(const int *i=connI;i!=connI+nbOfCells;i++)
7009 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7010 tmp[std::distance(connI,i)]=j++;
7012 DataArrayInt *ret=DataArrayInt::New();
7013 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7014 ret->copyStringInfoFrom(*da);
7015 int *retPtr=ret->getPointer();
7016 const int *daPtr=da->getConstPointer();
7017 int nbOfElems=da->getNbOfElems();
7018 for(int k=0;k<nbOfElems;k++)
7019 retPtr[k]=tmp[daPtr[k]];
7025 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7026 * This method \b works \b for mesh sorted by type.
7027 * cells whose ids is in 'idsPerGeoType' array.
7028 * This method conserves coords and name of mesh.
7030 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7032 std::vector<int> code=getDistributionOfTypes();
7033 std::size_t nOfTypesInThis=code.size()/3;
7034 int sz=0,szOfType=0;
7035 for(std::size_t i=0;i<nOfTypesInThis;i++)
7040 szOfType=code[3*i+1];
7042 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7043 if(*work<0 || *work>=szOfType)
7045 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7046 oss << ". It should be in [0," << szOfType << ") !";
7047 throw INTERP_KERNEL::Exception(oss.str().c_str());
7049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7050 int *idsPtr=idsTokeep->getPointer();
7052 for(std::size_t i=0;i<nOfTypesInThis;i++)
7055 for(int j=0;j<code[3*i+1];j++)
7058 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7059 offset+=code[3*i+1];
7061 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7062 ret->copyTinyInfoFrom(this);
7067 * This method returns a vector of size 'this->getNumberOfCells()'.
7068 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
7070 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7072 int ncell=getNumberOfCells();
7073 std::vector<bool> ret(ncell);
7074 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7075 const int *c=getNodalConnectivity()->getConstPointer();
7076 for(int i=0;i<ncell;i++)
7078 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7079 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7080 ret[i]=cm.isQuadratic();
7086 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
7088 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7090 if(other->getType()!=UNSTRUCTURED)
7091 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7092 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7093 return MergeUMeshes(this,otherC);
7097 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7098 * computed by averaging coordinates of cell nodes, so this method is not a right
7099 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7100 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7101 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7102 * components. The caller is to delete this array using decrRef() as it is
7104 * \throw If the coordinates array is not set.
7105 * \throw If the nodal connectivity of cells is not defined.
7106 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7108 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7110 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7111 int spaceDim=getSpaceDimension();
7112 int nbOfCells=getNumberOfCells();
7113 ret->alloc(nbOfCells,spaceDim);
7114 ret->copyStringInfoFrom(*getCoords());
7115 double *ptToFill=ret->getPointer();
7116 const int *nodal=_nodal_connec->getConstPointer();
7117 const int *nodalI=_nodal_connec_index->getConstPointer();
7118 const double *coor=_coords->getConstPointer();
7119 for(int i=0;i<nbOfCells;i++)
7121 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7122 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7129 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7130 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7132 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7133 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7135 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7136 * \throw If \a this is not fully defined (coordinates and connectivity)
7137 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7139 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7141 checkFullyDefined();
7142 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7143 int spaceDim=getSpaceDimension();
7144 int nbOfCells=getNumberOfCells();
7145 int nbOfNodes=getNumberOfNodes();
7146 ret->alloc(nbOfCells,spaceDim);
7147 double *ptToFill=ret->getPointer();
7148 const int *nodal=_nodal_connec->getConstPointer();
7149 const int *nodalI=_nodal_connec_index->getConstPointer();
7150 const double *coor=_coords->getConstPointer();
7151 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7153 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7154 std::fill(ptToFill,ptToFill+spaceDim,0.);
7155 if(type!=INTERP_KERNEL::NORM_POLYHED)
7157 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7159 if(*conn>=0 && *conn<nbOfNodes)
7160 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7163 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7164 throw INTERP_KERNEL::Exception(oss.str().c_str());
7167 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7168 if(nbOfNodesInCell>0)
7169 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7172 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7173 throw INTERP_KERNEL::Exception(oss.str().c_str());
7178 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7180 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7182 if(*it>=0 && *it<nbOfNodes)
7183 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7186 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7187 throw INTERP_KERNEL::Exception(oss.str().c_str());
7191 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7194 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7195 throw INTERP_KERNEL::Exception(oss.str().c_str());
7203 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7204 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7205 * are specified via an array of cell ids.
7206 * \warning Validity of the specified cell ids is not checked!
7207 * Valid range is [ 0, \a this->getNumberOfCells() ).
7208 * \param [in] begin - an array of cell ids of interest.
7209 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7210 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7211 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7212 * caller is to delete this array using decrRef() as it is no more needed.
7213 * \throw If the coordinates array is not set.
7214 * \throw If the nodal connectivity of cells is not defined.
7216 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7217 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7219 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7221 DataArrayDouble *ret=DataArrayDouble::New();
7222 int spaceDim=getSpaceDimension();
7223 int nbOfTuple=(int)std::distance(begin,end);
7224 ret->alloc(nbOfTuple,spaceDim);
7225 double *ptToFill=ret->getPointer();
7226 double *tmp=new double[spaceDim];
7227 const int *nodal=_nodal_connec->getConstPointer();
7228 const int *nodalI=_nodal_connec_index->getConstPointer();
7229 const double *coor=_coords->getConstPointer();
7230 for(const int *w=begin;w!=end;w++)
7232 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7233 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7241 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7244 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7247 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7248 da->checkAllocated();
7249 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7251 int nbOfTuples=da->getNumberOfTuples();
7252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7254 c->alloc(2*nbOfTuples,1);
7255 cI->alloc(nbOfTuples+1,1);
7256 int *cp=c->getPointer();
7257 int *cip=cI->getPointer();
7259 for(int i=0;i<nbOfTuples;i++)
7261 *cp++=INTERP_KERNEL::NORM_POINT1;
7265 ret->setConnectivity(c,cI,true);
7269 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7270 * Cells and nodes of
7271 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7272 * \param [in] mesh1 - the first mesh.
7273 * \param [in] mesh2 - the second mesh.
7274 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7275 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7276 * is no more needed.
7277 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7278 * \throw If the coordinates array is not set in none of the meshes.
7279 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7280 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7282 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7284 std::vector<const MEDCouplingUMesh *> tmp(2);
7285 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7286 return MergeUMeshes(tmp);
7290 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7291 * Cells and nodes of
7292 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7293 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7294 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7295 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7296 * is no more needed.
7297 * \throw If \a a.size() == 0.
7298 * \throw If \a a[ *i* ] == NULL.
7299 * \throw If the coordinates array is not set in none of the meshes.
7300 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7301 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7303 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7305 std::size_t sz=a.size();
7307 return MergeUMeshesLL(a);
7308 for(std::size_t ii=0;ii<sz;ii++)
7311 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7312 throw INTERP_KERNEL::Exception(oss.str().c_str());
7314 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7315 std::vector< const MEDCouplingUMesh * > aa(sz);
7317 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7319 const MEDCouplingUMesh *cur=a[i];
7320 const DataArrayDouble *coo=cur->getCoords();
7322 spaceDim=coo->getNumberOfComponents();
7325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7326 for(std::size_t i=0;i<sz;i++)
7328 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7331 return MergeUMeshesLL(aa);
7336 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7339 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7340 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7341 int meshDim=(*it)->getMeshDimension();
7342 int nbOfCells=(*it)->getNumberOfCells();
7343 int meshLgth=(*it++)->getMeshLength();
7344 for(;it!=a.end();it++)
7346 if(meshDim!=(*it)->getMeshDimension())
7347 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7348 nbOfCells+=(*it)->getNumberOfCells();
7349 meshLgth+=(*it)->getMeshLength();
7351 std::vector<const MEDCouplingPointSet *> aps(a.size());
7352 std::copy(a.begin(),a.end(),aps.begin());
7353 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7354 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7355 ret->setCoords(pts);
7356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7357 c->alloc(meshLgth,1);
7358 int *cPtr=c->getPointer();
7359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7360 cI->alloc(nbOfCells+1,1);
7361 int *cIPtr=cI->getPointer();
7365 for(it=a.begin();it!=a.end();it++)
7367 int curNbOfCell=(*it)->getNumberOfCells();
7368 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7369 const int *curC=(*it)->_nodal_connec->getConstPointer();
7370 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7371 for(int j=0;j<curNbOfCell;j++)
7373 const int *src=curC+curCI[j];
7375 for(;src!=curC+curCI[j+1];src++,cPtr++)
7383 offset+=curCI[curNbOfCell];
7384 offset2+=(*it)->getNumberOfNodes();
7387 ret->setConnectivity(c,cI,true);
7394 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7395 * dimension and sharing the node coordinates array.
7396 * All cells of the first mesh precede all cells of the second mesh
7397 * within the result mesh.
7398 * \param [in] mesh1 - the first mesh.
7399 * \param [in] mesh2 - the second mesh.
7400 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7401 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7402 * is no more needed.
7403 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7404 * \throw If the meshes do not share the node coordinates array.
7405 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7406 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7408 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7410 std::vector<const MEDCouplingUMesh *> tmp(2);
7411 tmp[0]=mesh1; tmp[1]=mesh2;
7412 return MergeUMeshesOnSameCoords(tmp);
7416 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7417 * dimension and sharing the node coordinates array.
7418 * All cells of the *i*-th mesh precede all cells of the
7419 * (*i*+1)-th mesh within the result mesh.
7420 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7421 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7422 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7423 * is no more needed.
7424 * \throw If \a a.size() == 0.
7425 * \throw If \a a[ *i* ] == NULL.
7426 * \throw If the meshes do not share the node coordinates array.
7427 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7428 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7430 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7433 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7434 for(std::size_t ii=0;ii<meshes.size();ii++)
7437 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7438 throw INTERP_KERNEL::Exception(oss.str().c_str());
7440 const DataArrayDouble *coords=meshes.front()->getCoords();
7441 int meshDim=meshes.front()->getMeshDimension();
7442 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7444 int meshIndexLgth=0;
7445 for(;iter!=meshes.end();iter++)
7447 if(coords!=(*iter)->getCoords())
7448 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7449 if(meshDim!=(*iter)->getMeshDimension())
7450 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7451 meshLgth+=(*iter)->getMeshLength();
7452 meshIndexLgth+=(*iter)->getNumberOfCells();
7454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7455 nodal->alloc(meshLgth,1);
7456 int *nodalPtr=nodal->getPointer();
7457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7458 nodalIndex->alloc(meshIndexLgth+1,1);
7459 int *nodalIndexPtr=nodalIndex->getPointer();
7461 for(iter=meshes.begin();iter!=meshes.end();iter++)
7463 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7464 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7465 int nbOfCells=(*iter)->getNumberOfCells();
7466 int meshLgth2=(*iter)->getMeshLength();
7467 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7468 if(iter!=meshes.begin())
7469 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7471 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7474 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7475 ret->setName("merge");
7476 ret->setMeshDimension(meshDim);
7477 ret->setConnectivity(nodal,nodalIndex,true);
7478 ret->setCoords(coords);
7483 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7484 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7485 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7486 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7487 * New" mode are returned for each input mesh.
7488 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7489 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7490 * valid values [0,1,2], see zipConnectivityTraducer().
7491 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7492 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7493 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7495 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7496 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7497 * is no more needed.
7498 * \throw If \a meshes.size() == 0.
7499 * \throw If \a meshes[ *i* ] == NULL.
7500 * \throw If the meshes do not share the node coordinates array.
7501 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7502 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7503 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7504 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7506 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7508 //All checks are delegated to MergeUMeshesOnSameCoords
7509 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7511 corr.resize(meshes.size());
7512 std::size_t nbOfMeshes=meshes.size();
7514 const int *o2nPtr=o2n->getConstPointer();
7515 for(std::size_t i=0;i<nbOfMeshes;i++)
7517 DataArrayInt *tmp=DataArrayInt::New();
7518 int curNbOfCells=meshes[i]->getNumberOfCells();
7519 tmp->alloc(curNbOfCells,1);
7520 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7521 offset+=curNbOfCells;
7522 tmp->setName(meshes[i]->getName());
7529 * Makes all given meshes share the nodal connectivity array. The common connectivity
7530 * array is created by concatenating the connectivity arrays of all given meshes. All
7531 * the given meshes must be of the same space dimension but dimension of cells **can
7532 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7533 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7534 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7535 * \param [in,out] meshes - a vector of meshes to update.
7536 * \throw If any of \a meshes is NULL.
7537 * \throw If the coordinates array is not set in any of \a meshes.
7538 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7539 * \throw If \a meshes are of different space dimension.
7541 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7543 std::size_t sz=meshes.size();
7546 std::vector< const DataArrayDouble * > coords(meshes.size());
7547 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7548 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7552 (*it)->checkConnectivityFullyDefined();
7553 const DataArrayDouble *coo=(*it)->getCoords();
7558 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7559 oss << " has no coordinate array defined !";
7560 throw INTERP_KERNEL::Exception(oss.str().c_str());
7565 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7566 oss << " is null !";
7567 throw INTERP_KERNEL::Exception(oss.str().c_str());
7570 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7571 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7572 int offset=(*it)->getNumberOfNodes();
7573 (*it++)->setCoords(res);
7574 for(;it!=meshes.end();it++)
7576 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7577 (*it)->setCoords(res);
7578 (*it)->shiftNodeNumbersInConn(offset);
7579 offset+=oldNumberOfNodes;
7584 * Merges nodes coincident with a given precision within all given meshes that share
7585 * the nodal connectivity array. The given meshes **can be of different** mesh
7586 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7587 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7588 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7589 * \param [in,out] meshes - a vector of meshes to update.
7590 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7591 * \throw If any of \a meshes is NULL.
7592 * \throw If the \a meshes do not share the same node coordinates array.
7593 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7595 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7599 std::set<const DataArrayDouble *> s;
7600 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7603 s.insert((*it)->getCoords());
7606 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 !";
7607 throw INTERP_KERNEL::Exception(oss.str().c_str());
7612 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 !";
7613 throw INTERP_KERNEL::Exception(oss.str().c_str());
7615 const DataArrayDouble *coo=*(s.begin());
7619 DataArrayInt *comm,*commI;
7620 coo->findCommonTuples(eps,-1,comm,commI);
7621 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7622 int oldNbOfNodes=coo->getNumberOfTuples();
7624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7625 if(oldNbOfNodes==newNbOfNodes)
7627 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7628 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7630 (*it)->renumberNodesInConn(o2n->getConstPointer());
7631 (*it)->setCoords(newCoords);
7636 * 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.
7637 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7638 * @param isQuad specifies the policy of connectivity.
7639 * @ret in/out parameter in which the result will be append
7641 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7643 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7644 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7645 ret.push_back(cm.getExtrudedType());
7646 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7649 case INTERP_KERNEL::NORM_POINT1:
7651 ret.push_back(connBg[1]);
7652 ret.push_back(connBg[1]+nbOfNodesPerLev);
7655 case INTERP_KERNEL::NORM_SEG2:
7657 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7658 ret.insert(ret.end(),conn,conn+4);
7661 case INTERP_KERNEL::NORM_SEG3:
7663 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7664 ret.insert(ret.end(),conn,conn+8);
7667 case INTERP_KERNEL::NORM_QUAD4:
7669 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7670 ret.insert(ret.end(),conn,conn+8);
7673 case INTERP_KERNEL::NORM_TRI3:
7675 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7676 ret.insert(ret.end(),conn,conn+6);
7679 case INTERP_KERNEL::NORM_TRI6:
7681 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,
7682 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7683 ret.insert(ret.end(),conn,conn+15);
7686 case INTERP_KERNEL::NORM_QUAD8:
7689 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7690 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7691 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7693 ret.insert(ret.end(),conn,conn+20);
7696 case INTERP_KERNEL::NORM_POLYGON:
7698 std::back_insert_iterator< std::vector<int> > ii(ret);
7699 std::copy(connBg+1,connEnd,ii);
7701 std::reverse_iterator<const int *> rConnBg(connEnd);
7702 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7703 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7704 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7705 for(std::size_t i=0;i<nbOfRadFaces;i++)
7708 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7709 std::copy(conn,conn+4,ii);
7714 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7719 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
7721 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7723 double v[3]={0.,0.,0.};
7724 std::size_t sz=std::distance(begin,end);
7727 for(std::size_t i=0;i<sz;i++)
7729 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];
7730 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7731 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7733 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7737 * The polyhedron is specfied by its connectivity nodes in [begin,end).
7739 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7741 std::vector<std::pair<int,int> > edges;
7742 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7743 const int *bgFace=begin;
7744 for(std::size_t i=0;i<nbOfFaces;i++)
7746 const int *endFace=std::find(bgFace+1,end,-1);
7747 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7748 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7750 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7751 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7753 edges.push_back(p1);
7757 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7761 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
7763 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7765 double vec0[3],vec1[3];
7766 std::size_t sz=std::distance(begin,end);
7768 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7769 int nbOfNodes=(int)sz/2;
7770 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7771 const double *pt0=coords+3*begin[0];
7772 const double *pt1=coords+3*begin[nbOfNodes];
7773 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7774 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7777 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7779 std::size_t sz=std::distance(begin,end);
7780 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7781 std::size_t nbOfNodes(sz/2);
7782 std::copy(begin,end,(int *)tmp);
7783 for(std::size_t j=1;j<nbOfNodes;j++)
7785 begin[j]=tmp[nbOfNodes-j];
7786 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7790 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7792 std::size_t sz=std::distance(begin,end);
7794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7795 double vec0[3],vec1[3];
7796 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7797 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];
7798 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;
7801 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7803 std::size_t sz=std::distance(begin,end);
7805 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7807 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7808 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7809 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7813 * 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)
7814 * 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
7817 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7818 * \param [in] coords the coordinates with nb of components exactly equal to 3
7819 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7820 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7821 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7823 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7825 int nbFaces=std::count(begin+1,end,-1)+1;
7826 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7827 double *vPtr=v->getPointer();
7828 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7829 double *pPtr=p->getPointer();
7830 const int *stFaceConn=begin+1;
7831 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7833 const int *endFaceConn=std::find(stFaceConn,end,-1);
7834 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7835 stFaceConn=endFaceConn+1;
7837 pPtr=p->getPointer(); vPtr=v->getPointer();
7838 DataArrayInt *comm1=0,*commI1=0;
7839 v->findCommonTuples(eps,-1,comm1,commI1);
7840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7841 const int *comm1Ptr=comm1->getConstPointer();
7842 const int *commI1Ptr=commI1->getConstPointer();
7843 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7844 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7846 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7847 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7848 mm->finishInsertingCells();
7850 for(int i=0;i<nbOfGrps1;i++)
7852 int vecId=comm1Ptr[commI1Ptr[i]];
7853 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7854 DataArrayInt *comm2=0,*commI2=0;
7855 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7857 const int *comm2Ptr=comm2->getConstPointer();
7858 const int *commI2Ptr=commI2->getConstPointer();
7859 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7860 for(int j=0;j<nbOfGrps2;j++)
7862 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7864 res->insertAtTheEnd(begin,end);
7865 res->pushBackSilent(-1);
7869 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7870 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7871 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7872 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7873 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7874 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7877 const int *idsNodePtr=idsNode->getConstPointer();
7878 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];
7879 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7880 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7881 if(std::abs(norm)>eps)
7883 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7884 mm3->rotate(center,vec,angle);
7886 mm3->changeSpaceDimension(2);
7887 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7888 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7889 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7890 int nbOfCells=mm4->getNumberOfCells();
7891 for(int k=0;k<nbOfCells;k++)
7894 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7895 res->pushBackSilent(idsNodePtr[*work]);
7896 res->pushBackSilent(-1);
7901 res->popBackSilent();
7905 * 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
7906 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
7908 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7909 * \param [in] coords coordinates expected to have 3 components.
7910 * \param [in] begin start of the nodal connectivity of the face.
7911 * \param [in] end end of the nodal connectivity (excluded) of the face.
7912 * \param [out] v the normalized vector of size 3
7913 * \param [out] p the pos of plane
7915 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7917 std::size_t nbPoints=std::distance(begin,end);
7919 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7922 bool refFound=false;
7923 for(;j<nbPoints-1 && !refFound;j++)
7925 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7926 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7927 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7928 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7932 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7935 for(std::size_t i=j;i<nbPoints-1;i++)
7938 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7939 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7940 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7941 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7944 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7945 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];
7946 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7949 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7950 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7954 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7958 * This method tries to obtain a well oriented polyhedron.
7959 * If the algorithm fails, an exception will be thrown.
7961 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7963 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7964 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7965 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7967 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7968 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7969 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7971 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7974 std::size_t smthChanged=0;
7975 for(std::size_t i=0;i<nbOfFaces;i++)
7977 endFace=std::find(bgFace+1,end,-1);
7978 nbOfEdgesInFace=std::distance(bgFace,endFace);
7982 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7984 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7985 std::pair<int,int> p2(p1.second,p1.first);
7986 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7987 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7988 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7993 std::reverse(bgFace+1,endFace);
7994 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7996 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7997 std::pair<int,int> p2(p1.second,p1.first);
7998 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7999 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8000 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8001 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8002 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8003 if(it!=edgesOK.end())
8006 edgesFinished.push_back(p1);
8009 edgesOK.push_back(p1);
8016 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8018 if(!edgesOK.empty())
8019 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8020 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8021 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8023 for(std::size_t i=0;i<nbOfFaces;i++)
8025 endFace=std::find(bgFace+1,end,-1);
8026 std::reverse(bgFace+1,endFace);
8033 * This method makes the assumption spacedimension == meshdimension == 2.
8034 * This method works only for linear cells.
8036 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8038 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
8040 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8041 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8042 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8043 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8044 int nbOfNodesExpected=m->getNumberOfNodes();
8045 if(m->getNumberOfCells()!=nbOfNodesExpected)
8046 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8048 const int *n2oPtr=n2o->getConstPointer();
8049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8050 m->getReverseNodalConnectivity(revNodal,revNodalI);
8051 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8052 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8053 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8055 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
8056 if(nbOfNodesExpected<1)
8059 int prevNode=nodalPtr[nodalIPtr[0]+1];
8060 *work++=n2oPtr[prevNode];
8061 for(int i=1;i<nbOfNodesExpected;i++)
8063 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8065 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8066 conn.erase(prevNode);
8069 int curNode=*(conn.begin());
8070 *work++=n2oPtr[curNode];
8071 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8072 shar.erase(prevCell);
8075 prevCell=*(shar.begin());
8079 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8085 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8091 * This method makes the assumption spacedimension == meshdimension == 3.
8092 * This method works only for linear cells.
8094 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8096 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8098 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8099 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8100 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8101 const int *conn=m->getNodalConnectivity()->getConstPointer();
8102 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8103 int nbOfCells=m->getNumberOfCells();
8104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8105 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8108 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8109 for(int i=1;i<nbOfCells;i++)
8112 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8118 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8119 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8121 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8125 for(int i=0;i<nbOfNodesInCell;i++)
8126 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8127 else if(spaceDim==2)
8129 for(int i=0;i<nbOfNodesInCell;i++)
8131 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8136 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8139 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8141 int nbOfCells=getNumberOfCells();
8143 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8144 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};
8145 ofs << " <" << getVTKDataSetType() << ">\n";
8146 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8147 ofs << " <PointData>\n" << pointData << std::endl;
8148 ofs << " </PointData>\n";
8149 ofs << " <CellData>\n" << cellData << std::endl;
8150 ofs << " </CellData>\n";
8151 ofs << " <Points>\n";
8152 if(getSpaceDimension()==3)
8153 _coords->writeVTK(ofs,8,"Points");
8156 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8157 coo->writeVTK(ofs,8,"Points");
8159 ofs << " </Points>\n";
8160 ofs << " <Cells>\n";
8161 const int *cPtr=_nodal_connec->getConstPointer();
8162 const int *cIPtr=_nodal_connec_index->getConstPointer();
8163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8167 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8168 int szFaceOffsets=0,szConn=0;
8169 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8172 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8175 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8176 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8180 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8181 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8182 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8183 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8184 w4=std::copy(c.begin(),c.end(),w4);
8187 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8188 types->writeVTK(ofs,8,"UInt8","types");
8189 offsets->writeVTK(ofs,8,"Int32","offsets");
8190 if(szFaceOffsets!=0)
8191 {//presence of Polyhedra
8192 connectivity->reAlloc(szConn);
8193 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8195 w1=faces->getPointer();
8196 for(int i=0;i<nbOfCells;i++)
8197 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8199 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8201 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8202 for(int j=0;j<nbFaces;j++)
8204 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8205 *w1++=(int)std::distance(w6,w5);
8206 w1=std::copy(w6,w5,w1);
8210 faces->writeVTK(ofs,8,"Int32","faces");
8212 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8213 ofs << " </Cells>\n";
8214 ofs << " </Piece>\n";
8215 ofs << " </" << getVTKDataSetType() << ">\n";
8218 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8220 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8222 { stream << " Not set !"; return ; }
8223 stream << " Mesh dimension : " << _mesh_dim << ".";
8227 { stream << " No coordinates set !"; return ; }
8228 if(!_coords->isAllocated())
8229 { stream << " Coordinates set but not allocated !"; return ; }
8230 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8231 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8232 if(!_nodal_connec_index)
8233 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8234 if(!_nodal_connec_index->isAllocated())
8235 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8236 int lgth=_nodal_connec_index->getNumberOfTuples();
8237 int cpt=_nodal_connec_index->getNumberOfComponents();
8238 if(cpt!=1 || lgth<1)
8240 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8243 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8245 return std::string("UnstructuredGrid");
8249 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8250 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8251 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8253 * \param [in] m1 - the first input mesh which is a partitioned object.
8254 * \param [in] m2 - the second input mesh which is a partition tool.
8255 * \param [in] eps - precision used to detect coincident mesh entities.
8256 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8257 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8258 * this array using decrRef() as it is no more needed.
8259 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8260 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8261 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8262 * any cell of \a m2. The caller is to delete this array using decrRef() as
8263 * it is no more needed.
8264 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8265 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8266 * is no more needed.
8267 * \throw If the coordinates array is not set in any of the meshes.
8268 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8269 * \throw If any of the meshes is not a 2D mesh in 2D space.
8271 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8273 m1->checkFullyDefined();
8274 m2->checkFullyDefined();
8275 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8277 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8278 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8279 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8280 std::vector<double> addCoo,addCoordsQuadratic;
8281 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8282 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8283 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8284 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8285 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8287 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8288 std::vector< std::vector<int> > intersectEdge2;
8289 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8290 subDiv2.clear(); dd5=0; dd6=0;
8291 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8292 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8293 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8294 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8296 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8297 addCooDa->alloc((int)(addCoo.size())/2,2);
8298 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8299 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8300 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8301 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8302 std::vector<const DataArrayDouble *> coordss(4);
8303 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8304 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8305 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8310 ret->setConnectivity(conn,connI,true);
8311 ret->setCoords(coo);
8312 cellNb1=c1.retn(); cellNb2=c2.retn();
8316 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8317 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8318 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8319 const std::vector<double>& addCoords,
8320 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8322 static const int SPACEDIM=2;
8323 std::vector<double> bbox1,bbox2;
8324 const double *coo1=m1->getCoords()->getConstPointer();
8325 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8326 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8327 int offset1=m1->getNumberOfNodes();
8328 const double *coo2=m2->getCoords()->getConstPointer();
8329 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8330 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8331 int offset2=offset1+m2->getNumberOfNodes();
8332 int offset3=offset2+((int)addCoords.size())/2;
8333 m1->getBoundingBoxForBBTree(bbox1);
8334 m2->getBoundingBoxForBBTree(bbox2);
8335 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8336 int ncell1=m1->getNumberOfCells();
8338 for(int i=0;i<ncell1;i++)
8340 std::vector<int> candidates2;
8341 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8342 std::map<INTERP_KERNEL::Node *,int> mapp;
8343 std::map<int,INTERP_KERNEL::Node *> mappRev;
8344 INTERP_KERNEL::QuadraticPolygon pol1;
8345 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8346 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8347 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8348 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8349 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8351 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
8352 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8353 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8354 for(it1.first();!it1.finished();it1.next())
8355 edges1.insert(it1.current()->getPtr());
8357 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8358 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8360 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8362 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8363 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8364 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8365 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8366 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8369 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8371 pol1.initLocationsWithOther(pol2s[ii]);
8372 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8373 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8374 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8380 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8382 catch(INTERP_KERNEL::Exception& e)
8384 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();
8385 throw INTERP_KERNEL::Exception(oss.str().c_str());
8388 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8389 (*it).second->decrRef();
8394 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8397 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8398 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8399 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8400 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8401 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8403 static const int SPACEDIM=2;
8404 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8405 desc2=DataArrayInt::New();
8406 descIndx2=DataArrayInt::New();
8407 revDesc2=DataArrayInt::New();
8408 revDescIndx2=DataArrayInt::New();
8409 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8410 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8411 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8412 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8413 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8414 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8415 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8416 std::vector<double> bbox1,bbox2;
8417 m1Desc->getBoundingBoxForBBTree(bbox1);
8418 m2Desc->getBoundingBoxForBBTree(bbox2);
8419 int ncell1=m1Desc->getNumberOfCells();
8420 int ncell2=m2Desc->getNumberOfCells();
8421 intersectEdge1.resize(ncell1);
8422 colinear2.resize(ncell2);
8423 subDiv2.resize(ncell2);
8424 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8425 std::vector<int> candidates1(1);
8426 int offset1=m1->getNumberOfNodes();
8427 int offset2=offset1+m2->getNumberOfNodes();
8428 for(int i=0;i<ncell1;i++)
8430 std::vector<int> candidates2;
8431 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8432 if(!candidates2.empty())
8434 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8435 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8437 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8438 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8443 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8445 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8446 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8450 * This method performs the 2nd step of Partition of 2D mesh.
8451 * This method has 4 inputs :
8452 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8453 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8454 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8455 * 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'
8456 * @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'
8457 * @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.
8458 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8460 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)
8462 int offset1=m1->getNumberOfNodes();
8463 int ncell=m2->getNumberOfCells();
8464 const int *c=m2->getNodalConnectivity()->getConstPointer();
8465 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8466 const double *coo=m2->getCoords()->getConstPointer();
8467 const double *cooBis=m1->getCoords()->getConstPointer();
8468 int offset2=offset1+m2->getNumberOfNodes();
8469 intersectEdge.resize(ncell);
8470 for(int i=0;i<ncell;i++,cI++)
8472 const std::vector<int>& divs=subDiv[i];
8473 int nnode=cI[1]-cI[0]-1;
8474 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8475 std::map<INTERP_KERNEL::Node *, int> mapp22;
8476 for(int j=0;j<nnode;j++)
8478 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8479 int nnid=c[(*cI)+j+1];
8480 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8481 mapp22[nn]=nnid+offset1;
8483 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8484 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8485 ((*it).second.first)->decrRef();
8486 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8487 std::map<INTERP_KERNEL::Node *,int> mapp3;
8488 for(std::size_t j=0;j<divs.size();j++)
8491 INTERP_KERNEL::Node *tmp=0;
8493 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8495 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8497 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8501 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8502 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8509 * 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).
8510 * 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
8511 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8512 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8513 * @param nodesOnPlane, returns all the nodes that are on the plane.
8514 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
8515 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8516 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
8517 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8518 * @param desc is the descending connectivity 3DSurf->3DCurve
8519 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
8520 * @param cut3DSuf input/output param.
8522 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8523 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8524 const int *desc, const int *descIndx,
8525 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8527 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8528 int nbOf3DSurfCell=(int)cut3DSurf.size();
8529 for(int i=0;i<nbOf3DSurfCell;i++)
8531 std::vector<int> res;
8532 int offset=descIndx[i];
8533 int nbOfSeg=descIndx[i+1]-offset;
8534 for(int j=0;j<nbOfSeg;j++)
8536 int edgeId=desc[offset+j];
8537 int status=cut3DCurve[edgeId];
8541 res.push_back(status);
8544 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8545 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8553 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8559 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8560 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8563 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8567 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8572 {// case when plane is on a multi colinear edge of a polyhedron
8573 if((int)res.size()==2*nbOfSeg)
8575 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8585 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8586 * 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).
8587 * 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
8588 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8589 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8590 * @param desc is the descending connectivity 3D->3DSurf
8591 * @param descIndx is the descending connectivity index 3D->3DSurf
8593 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8594 const int *desc, const int *descIndx,
8595 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8597 checkFullyDefined();
8598 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8599 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8600 const int *nodal3D=_nodal_connec->getConstPointer();
8601 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8602 int nbOfCells=getNumberOfCells();
8603 for(int i=0;i<nbOfCells;i++)
8605 std::map<int, std::set<int> > m;
8606 int offset=descIndx[i];
8607 int nbOfFaces=descIndx[i+1]-offset;
8610 for(int j=0;j<nbOfFaces;j++)
8612 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8613 if(p.first!=-1 && p.second!=-1)
8617 start=p.first; end=p.second;
8618 m[p.first].insert(p.second);
8619 m[p.second].insert(p.first);
8623 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8624 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8625 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8626 INTERP_KERNEL::NormalizedCellType cmsId;
8627 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8628 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8629 for(unsigned k=0;k<nbOfNodesSon;k++)
8631 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8632 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8639 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8643 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8644 const std::set<int>& s=(*it).second;
8645 std::set<int> s2; s2.insert(prev);
8647 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8650 int val=*s3.begin();
8651 conn.push_back(start);
8658 conn.push_back(end);
8661 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8662 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8663 cellIds->pushBackSilent(i);
8669 * 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
8670 * 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
8671 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8672 * 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
8673 * 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.
8675 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8677 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8679 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8682 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8683 if(cm.getDimension()==2)
8685 const int *node=nodalConnBg+1;
8686 int startNode=*node++;
8687 double refX=coords[2*startNode];
8688 for(;node!=nodalConnEnd;node++)
8690 if(coords[2*(*node)]<refX)
8693 refX=coords[2*startNode];
8696 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8700 double angle0=-M_PI/2;
8706 while(nextNode!=startNode)
8710 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8712 if(*node!=tmpOut.back() && *node!=prevNode)
8714 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8715 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8720 res=angle0-angleM+2.*M_PI;
8729 if(nextNode!=startNode)
8731 angle0=angleNext-M_PI;
8734 prevNode=tmpOut.back();
8735 tmpOut.push_back(nextNode);
8738 std::vector<int> tmp3(2*(sz-1));
8739 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8740 std::copy(nodalConnBg+1,nodalConnEnd,it);
8741 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8743 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8746 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8748 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8753 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8754 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8759 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8762 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8766 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8767 * 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.
8769 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8770 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8771 * \param [in,out] arr array in which the remove operation will be done.
8772 * \param [in,out] arrIndx array in the remove operation will modify
8773 * \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])
8774 * \return true if \b arr and \b arrIndx have been modified, false if not.
8776 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8778 if(!arrIndx || !arr)
8779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8780 if(offsetForRemoval<0)
8781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8782 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8783 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8784 int *arrIPtr=arrIndx->getPointer();
8787 const int *arrPtr=arr->getConstPointer();
8788 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8789 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8791 if(*arrIPtr-previousArrI>offsetForRemoval)
8793 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8795 if(s.find(*work)==s.end())
8796 arrOut.push_back(*work);
8799 previousArrI=*arrIPtr;
8800 *arrIPtr=(int)arrOut.size();
8802 if(arr->getNumberOfTuples()==(int)arrOut.size())
8804 arr->alloc((int)arrOut.size(),1);
8805 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8810 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8811 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8812 * The selection of extraction is done standardly in new2old format.
8813 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8815 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8816 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8817 * \param [in] arrIn arr origin array from which the extraction will be done.
8818 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8819 * \param [out] arrOut the resulting array
8820 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8822 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8823 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8825 if(!arrIn || !arrIndxIn)
8826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8827 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8828 const int *arrInPtr=arrIn->getConstPointer();
8829 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8830 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8831 int maxSizeOfArr=arrIn->getNumberOfTuples();
8832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8834 arrIo->alloc((int)(sz+1),1);
8835 const int *idsIt=idsOfSelectBg;
8836 int *work=arrIo->getPointer();
8839 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8841 if(*idsIt>=0 && *idsIt<nbOfGrps)
8842 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8845 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8846 throw INTERP_KERNEL::Exception(oss.str().c_str());
8852 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8853 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8854 throw INTERP_KERNEL::Exception(oss.str().c_str());
8857 arro->alloc(lgth,1);
8858 work=arro->getPointer();
8859 idsIt=idsOfSelectBg;
8860 for(std::size_t i=0;i<sz;i++,idsIt++)
8862 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8863 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8866 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8867 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8868 throw INTERP_KERNEL::Exception(oss.str().c_str());
8872 arrIndexOut=arrIo.retn();
8876 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8877 * 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
8878 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8879 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8881 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8882 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8883 * \param [in] arrIn arr origin array from which the extraction will be done.
8884 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8885 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8886 * \param [in] srcArrIndex index array of \b srcArr
8887 * \param [out] arrOut the resulting array
8888 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8890 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8892 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8893 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8894 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8896 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8900 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8901 std::vector<bool> v(nbOfTuples,true);
8903 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8904 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8905 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8907 if(*it>=0 && *it<nbOfTuples)
8910 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8914 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8915 throw INTERP_KERNEL::Exception(oss.str().c_str());
8918 srcArrIndexPtr=srcArrIndex->getConstPointer();
8919 arrIo->alloc(nbOfTuples+1,1);
8920 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8921 const int *arrInPtr=arrIn->getConstPointer();
8922 const int *srcArrPtr=srcArr->getConstPointer();
8923 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8924 int *arroPtr=arro->getPointer();
8925 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8929 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8930 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8934 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8935 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8936 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8940 arrIndexOut=arrIo.retn();
8944 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8945 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8947 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8948 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8949 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8950 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8951 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8952 * \param [in] srcArrIndex index array of \b srcArr
8954 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8956 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8957 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8959 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8960 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8961 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8962 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8963 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8964 int *arrInOutPtr=arrInOut->getPointer();
8965 const int *srcArrPtr=srcArr->getConstPointer();
8966 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8968 if(*it>=0 && *it<nbOfTuples)
8970 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8971 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8974 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] !";
8975 throw INTERP_KERNEL::Exception(oss.str().c_str());
8980 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8981 throw INTERP_KERNEL::Exception(oss.str().c_str());
8987 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8988 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8989 * 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]].
8990 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8991 * A negative value in \b arrIn means that it is ignored.
8992 * 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.
8994 * \param [in] arrIn arr origin array from which the extraction will be done.
8995 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8996 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8997 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8999 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9001 int seed=0,nbOfDepthPeelingPerformed=0;
9002 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9006 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9007 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9008 * 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]].
9009 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9010 * A negative value in \b arrIn means that it is ignored.
9011 * 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.
9012 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9013 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9014 * \param [in] arrIn arr origin array from which the extraction will be done.
9015 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9016 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9017 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9018 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9019 * \sa MEDCouplingUMesh::partitionBySpreadZone
9021 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9023 nbOfDepthPeelingPerformed=0;
9025 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9026 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9029 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9033 std::vector<bool> fetched(nbOfTuples,false);
9034 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9037 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)
9039 nbOfDepthPeelingPerformed=0;
9040 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9041 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9042 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9043 std::vector<bool> fetched2(nbOfTuples,false);
9045 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9047 if(*seedElt>=0 && *seedElt<nbOfTuples)
9048 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9050 { 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()); }
9052 const int *arrInPtr=arrIn->getConstPointer();
9053 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9054 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9055 std::vector<int> idsToFetch1(seedBg,seedEnd);
9056 std::vector<int> idsToFetch2;
9057 std::vector<int> *idsToFetch=&idsToFetch1;
9058 std::vector<int> *idsToFetchOther=&idsToFetch2;
9059 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9061 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9062 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9064 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9065 std::swap(idsToFetch,idsToFetchOther);
9066 idsToFetchOther->clear();
9067 nbOfDepthPeelingPerformed++;
9069 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9072 int *retPtr=ret->getPointer();
9073 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9080 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9081 * 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
9082 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9083 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9085 * \param [in] start begin of set of ids of the input extraction (included)
9086 * \param [in] end end of set of ids of the input extraction (excluded)
9087 * \param [in] step step of the set of ids in range mode.
9088 * \param [in] arrIn arr origin array from which the extraction will be done.
9089 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9090 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9091 * \param [in] srcArrIndex index array of \b srcArr
9092 * \param [out] arrOut the resulting array
9093 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9095 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9097 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9098 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9099 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9101 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9102 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9105 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9107 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9108 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9109 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9111 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9113 if(it>=0 && it<nbOfTuples)
9114 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9117 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9118 throw INTERP_KERNEL::Exception(oss.str().c_str());
9121 srcArrIndexPtr=srcArrIndex->getConstPointer();
9122 arrIo->alloc(nbOfTuples+1,1);
9123 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9124 const int *arrInPtr=arrIn->getConstPointer();
9125 const int *srcArrPtr=srcArr->getConstPointer();
9126 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9127 int *arroPtr=arro->getPointer();
9128 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9130 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9133 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9134 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9138 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9139 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9143 arrIndexOut=arrIo.retn();
9147 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9148 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9150 * \param [in] start begin of set of ids of the input extraction (included)
9151 * \param [in] end end of set of ids of the input extraction (excluded)
9152 * \param [in] step step of the set of ids in range mode.
9153 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9154 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9155 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9156 * \param [in] srcArrIndex index array of \b srcArr
9158 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9160 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9161 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9163 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9164 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9165 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9166 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9167 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9168 int *arrInOutPtr=arrInOut->getPointer();
9169 const int *srcArrPtr=srcArr->getConstPointer();
9170 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9172 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9174 if(it>=0 && it<nbOfTuples)
9176 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9177 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9180 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9181 throw INTERP_KERNEL::Exception(oss.str().c_str());
9186 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9187 throw INTERP_KERNEL::Exception(oss.str().c_str());
9193 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9194 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9195 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9196 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9197 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9199 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9201 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9203 checkFullyDefined();
9204 int mdim=getMeshDimension();
9205 int spaceDim=getSpaceDimension();
9207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9208 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9209 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9210 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9211 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9212 ret->setCoords(getCoords());
9213 ret->allocateCells((int)partition.size());
9215 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9217 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9222 cell=tmp->buildUnionOf2DMesh();
9225 cell=tmp->buildUnionOf3DMesh();
9228 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9231 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9234 ret->finishInsertingCells();
9239 * This method partitions \b this into contiguous zone.
9240 * This method only needs a well defined connectivity. Coordinates are not considered here.
9241 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9243 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9246 int nbOfCellsCur=getNumberOfCells();
9247 std::vector<DataArrayInt *> ret;
9250 DataArrayInt *neigh=0,*neighI=0;
9251 computeNeighborsOfCells(neigh,neighI);
9252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9253 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9254 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9256 while(seed<nbOfCellsCur)
9258 int nbOfPeelPerformed=0;
9259 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9260 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9262 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9263 ret.push_back((*it).retn());
9267 int nbOfCellsCur=getNumberOfCells();
9268 DataArrayInt *neigh=0,*neighI=0;
9269 computeNeighborsOfCells(neigh,neighI);
9270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9272 std::vector<DataArrayInt *> ret;
9273 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9274 while(nbOfCellsCur>0)
9276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9279 ret2.push_back(tmp2); ret.push_back(tmp2);
9280 nbOfCellsCur=tmp3->getNumberOfTuples();
9283 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9284 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9288 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9291 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9298 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9299 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9301 * \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.
9302 * \return a newly allocated DataArrayInt to be managed by the caller.
9303 * \throw In case of \a code has not the right format (typically of size 3*n)
9305 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9308 std::size_t nb=code.size()/3;
9309 if(code.size()%3!=0)
9310 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9311 ret->alloc((int)nb,2);
9312 int *retPtr=ret->getPointer();
9313 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9315 retPtr[0]=code[3*i+2];
9316 retPtr[1]=code[3*i+2]+code[3*i+1];
9321 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9322 _own_cell(true),_cell_id(-1),_nb_cell(0)
9327 _nb_cell=mesh->getNumberOfCells();
9331 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9339 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9340 _own_cell(false),_cell_id(bg-1),
9347 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9350 if(_cell_id<_nb_cell)
9359 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9365 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9367 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9370 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9376 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9384 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9390 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9395 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9400 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9402 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9405 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9410 _nb_cell=mesh->getNumberOfCells();
9414 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9421 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9423 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9424 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9425 if(_cell_id<_nb_cell)
9427 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9428 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9429 int startId=_cell_id;
9430 _cell_id+=nbOfElems;
9431 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9437 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9441 _conn=mesh->getNodalConnectivity()->getPointer();
9442 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9446 void MEDCouplingUMeshCell::next()
9448 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9453 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9456 std::string MEDCouplingUMeshCell::repr() const
9458 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9460 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9462 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9466 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9469 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9471 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9472 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9474 return INTERP_KERNEL::NORM_ERROR;
9477 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9480 if(_conn_lgth!=NOTICABLE_FIRST_VAL)