1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "InterpKernelAutoPtr.hxx"
37 #include "InterpKernelGeo2DNode.hxx"
38 #include "InterpKernelGeo2DEdgeLin.hxx"
39 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
40 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
49 using namespace ParaMEDMEM;
51 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 return new MEDCouplingUMesh;
60 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
63 ret->setName(meshName);
64 ret->setMeshDimension(meshDim);
69 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
70 * between \a this and the new mesh.
71 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
72 * delete this mesh using decrRef() as it is no more needed.
74 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
80 * Returns a new MEDCouplingMesh which is a copy of \a this one.
81 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
82 * this mesh are shared by the new mesh.
83 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
84 * delete this mesh using decrRef() as it is no more needed.
86 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 return new MEDCouplingUMesh(*this,recDeepCpy);
92 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
93 * The coordinates are shared between \a this and the returned instance.
95 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
96 * \sa MEDCouplingUMesh::deepCpy
98 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception)
100 checkConnectivityFullyDefined();
101 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
103 ret->setConnectivity(c,ci);
107 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
110 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
111 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
114 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
115 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
118 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
124 std::vector<RefCountObject *> MEDCouplingUMesh::getDirectChildren() const
126 std::vector<RefCountObject *> ret(MEDCouplingPointSet::getDirectChildren());
128 ret.push_back(const_cast<DataArrayInt *>(_nodal_connec));
129 if(_nodal_connec_index)
130 ret.push_back(const_cast<DataArrayInt *>(_nodal_connec_index));
134 void MEDCouplingUMesh::updateTime() const
136 MEDCouplingPointSet::updateTime();
139 updateTimeWith(*_nodal_connec);
141 if(_nodal_connec_index)
143 updateTimeWith(*_nodal_connec_index);
147 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
153 * then \a this mesh is most probably is writable, exchangeable and available for most
154 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
155 * this method to check that all is in order with \a this mesh.
156 * \throw If the mesh dimension is not set.
157 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
158 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
159 * \throw If the connectivity data array has more than one component.
160 * \throw If the connectivity data array has a named component.
161 * \throw If the connectivity index data array has more than one component.
162 * \throw If the connectivity index data array has a named component.
164 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
167 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169 MEDCouplingPointSet::checkCoherency();
170 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174 std::ostringstream message;
175 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
176 throw INTERP_KERNEL::Exception(message.str().c_str());
181 if(_nodal_connec->getNumberOfComponents()!=1)
182 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
183 if(_nodal_connec->getInfoOnComponent(0)!="")
184 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
188 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
189 if(_nodal_connec_index)
191 if(_nodal_connec_index->getNumberOfComponents()!=1)
192 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
193 if(_nodal_connec_index->getInfoOnComponent(0)!="")
194 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
198 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
202 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
203 * then \a this mesh is most probably is writable, exchangeable and available for all
204 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
205 * method thoroughly checks the nodal connectivity.
206 * \param [in] eps - a not used parameter.
207 * \throw If the mesh dimension is not set.
208 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
209 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
210 * \throw If the connectivity data array has more than one component.
211 * \throw If the connectivity data array has a named component.
212 * \throw If the connectivity index data array has more than one component.
213 * \throw If the connectivity index data array has a named component.
214 * \throw If number of nodes defining an element does not correspond to the type of element.
215 * \throw If the nodal connectivity includes an invalid node id.
217 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
222 int meshDim=getMeshDimension();
223 int nbOfNodes=getNumberOfNodes();
224 int nbOfCells=getNumberOfCells();
225 const int *ptr=_nodal_connec->getConstPointer();
226 const int *ptrI=_nodal_connec_index->getConstPointer();
227 for(int i=0;i<nbOfCells;i++)
229 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
230 if((int)cm.getDimension()!=meshDim)
232 std::ostringstream oss;
233 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
234 throw INTERP_KERNEL::Exception(oss.str().c_str());
236 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240 std::ostringstream oss;
241 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
242 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
243 throw INTERP_KERNEL::Exception(oss.str().c_str());
245 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
250 if(nodeId>=nbOfNodes)
252 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
253 throw INTERP_KERNEL::Exception(oss.str().c_str());
258 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
259 throw INTERP_KERNEL::Exception(oss.str().c_str());
263 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
266 throw INTERP_KERNEL::Exception(oss.str().c_str());
275 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
276 * then \a this mesh is most probably is writable, exchangeable and available for all
277 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
278 * \param [in] eps - a not used parameter.
279 * \throw If the mesh dimension is not set.
280 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
281 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
282 * \throw If the connectivity data array has more than one component.
283 * \throw If the connectivity data array has a named component.
284 * \throw If the connectivity index data array has more than one component.
285 * \throw If the connectivity index data array has a named component.
286 * \throw If number of nodes defining an element does not correspond to the type of element.
287 * \throw If the nodal connectivity includes an invalid node id.
289 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
291 checkCoherency1(eps);
295 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
296 * elements contained in the mesh. For more info on the mesh dimension see
297 * \ref MEDCouplingUMeshPage.
298 * \param [in] meshDim - a new mesh dimension.
299 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 if(meshDim<-1 || meshDim>3)
304 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
310 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
311 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
312 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
319 void MEDCouplingUMesh::allocateCells(int nbOfCells)
322 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
323 if(_nodal_connec_index)
325 _nodal_connec_index->decrRef();
329 _nodal_connec->decrRef();
331 _nodal_connec_index=DataArrayInt::New();
332 _nodal_connec_index->reserve(nbOfCells+1);
333 _nodal_connec_index->pushBackSilent(0);
334 _nodal_connec=DataArrayInt::New();
335 _nodal_connec->reserve(2*nbOfCells);
341 * Appends a cell to the connectivity array. For deeper understanding what is
342 * happening see \ref MEDCouplingUMeshNodalConnectivity.
343 * \param [in] type - type of cell to add.
344 * \param [in] size - number of nodes constituting this cell.
345 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
347 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
348 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
350 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
352 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
353 if(_nodal_connec_index==0)
354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
355 if((int)cm.getDimension()==_mesh_dim)
358 if(size!=(int)cm.getNumberOfNodes())
360 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
361 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
362 throw INTERP_KERNEL::Exception(oss.str().c_str());
364 int idx=_nodal_connec_index->back();
366 _nodal_connec_index->pushBackSilent(val);
367 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
372 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
373 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
374 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
375 throw INTERP_KERNEL::Exception(oss.str().c_str());
380 * Compacts data arrays to release unused memory. This method is to be called after
381 * finishing cell insertion using \a this->insertNextCell().
383 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
384 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
386 void MEDCouplingUMesh::finishInsertingCells()
388 _nodal_connec->pack();
389 _nodal_connec_index->pack();
390 _nodal_connec->declareAsNew();
391 _nodal_connec_index->declareAsNew();
396 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
397 * Useful for python users.
399 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
401 return new MEDCouplingUMeshCellIterator(this);
405 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
406 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
407 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
408 * Useful for python users.
410 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
412 if(!checkConsecutiveCellTypes())
413 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
414 return new MEDCouplingUMeshCellByTypeEntry(this);
418 * Returns a set of all cell types available in \a this mesh.
419 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
420 * \warning this method does not throw any exception even if \a this is not defined.
422 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
428 * This method is a method that compares \a this and \a other.
429 * This method compares \b all attributes, even names and component names.
431 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
434 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
435 std::ostringstream oss; oss.precision(15);
436 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
439 reason="mesh given in input is not castable in MEDCouplingUMesh !";
442 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
444 if(_mesh_dim!=otherC->_mesh_dim)
446 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
450 if(_types!=otherC->_types)
452 oss << "umesh geometric type mismatch :\nThis geometric types are :";
453 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
454 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
455 oss << "\nOther geometric types are :";
456 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
457 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
461 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
462 if(_nodal_connec==0 || otherC->_nodal_connec==0)
464 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
467 if(_nodal_connec!=otherC->_nodal_connec)
468 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
470 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
473 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
474 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
476 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
479 if(_nodal_connec_index!=otherC->_nodal_connec_index)
480 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
482 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
489 * Checks if data arrays of this mesh (node coordinates, nodal
490 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
492 * \param [in] other - the mesh to compare with.
493 * \param [in] prec - precision value used to compare node coordinates.
494 * \return bool - \a true if the two meshes are same.
496 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
498 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
501 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
503 if(_mesh_dim!=otherC->_mesh_dim)
505 if(_types!=otherC->_types)
507 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
508 if(_nodal_connec==0 || otherC->_nodal_connec==0)
510 if(_nodal_connec!=otherC->_nodal_connec)
511 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
513 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
514 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
516 if(_nodal_connec_index!=otherC->_nodal_connec_index)
517 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
523 * Checks if \a this and \a other meshes are geometrically equivalent with high
524 * probability, else an exception is thrown. The meshes are considered equivalent if
525 * (1) meshes contain the same number of nodes and the same number of elements of the
526 * same types (2) three cells of the two meshes (first, last and middle) are based
527 * on coincident nodes (with a specified precision).
528 * \param [in] other - the mesh to compare with.
529 * \param [in] prec - the precision used to compare nodes of the two meshes.
530 * \throw If the two meshes do not match.
532 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
534 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
535 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
537 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
541 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
542 * cells each node belongs to.
543 * \warning For speed reasons, this method does not check if node ids in the nodal
544 * connectivity correspond to the size of node coordinates array.
545 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
546 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
547 * dividing cell ids in \a revNodal into groups each referring to one
548 * node. Its every element (except the last one) is an index pointing to the
549 * first id of a group of cells. For example cells sharing the node #1 are
550 * described by following range of indices:
551 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
552 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
553 * Number of cells sharing the *i*-th node is
554 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
555 * \throw If the coordinates array is not set.
556 * \throw If the nodal connectivity of cells is not defined.
558 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
559 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
561 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
564 int nbOfNodes=getNumberOfNodes();
565 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
566 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
567 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
568 const int *conn=_nodal_connec->getConstPointer();
569 const int *connIndex=_nodal_connec_index->getConstPointer();
570 int nbOfCells=getNumberOfCells();
571 int nbOfEltsInRevNodal=0;
572 for(int eltId=0;eltId<nbOfCells;eltId++)
574 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
575 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
576 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
577 if(*iter>=0)//for polyhedrons
579 nbOfEltsInRevNodal++;
580 revNodalIndxPtr[(*iter)+1]++;
583 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
584 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
585 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
586 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
587 for(int eltId=0;eltId<nbOfCells;eltId++)
589 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
590 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
591 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
592 if(*iter>=0)//for polyhedrons
593 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
599 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
604 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
610 if(cm.getOrientationStatus(nb,conn1,conn2))
617 class MinusOneSonsGenerator
620 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
621 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
622 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
623 static const int DELTA=1;
625 const INTERP_KERNEL::CellModel& _cm;
628 class MinusOneSonsGeneratorBiQuadratic
631 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
632 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
633 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
634 static const int DELTA=1;
636 const INTERP_KERNEL::CellModel& _cm;
639 class MinusTwoSonsGenerator
642 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
643 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
644 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
645 static const int DELTA=2;
647 const INTERP_KERNEL::CellModel& _cm;
653 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
654 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
655 * describing correspondence between cells of \a this and the result meshes are
656 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
657 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
658 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
659 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
660 * \warning For speed reasons, this method does not check if node ids in the nodal
661 * connectivity correspond to the size of node coordinates array.
662 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
663 * to write this mesh to the MED file, its cells must be sorted using
664 * sortCellsInMEDFileFrmt().
665 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
666 * each cell of \a this mesh.
667 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
668 * dividing cell ids in \a desc into groups each referring to one
669 * cell of \a this mesh. Its every element (except the last one) is an index
670 * pointing to the first id of a group of cells. For example cells of the
671 * result mesh bounding the cell #1 of \a this mesh are described by following
673 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
674 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
675 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
676 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
677 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
678 * by each cell of the result mesh.
679 * \param [in,out] revDescIndx - the array, of length one more than number of cells
680 * in the result mesh,
681 * dividing cell ids in \a revDesc into groups each referring to one
682 * cell of the result mesh the same way as \a descIndx divides \a desc.
683 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
684 * delete this mesh using decrRef() as it is no more needed.
685 * \throw If the coordinates array is not set.
686 * \throw If the nodal connectivity of cells is node defined.
687 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
688 * revDescIndx == NULL.
690 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
691 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
692 * \sa buildDescendingConnectivity2()
694 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
696 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
700 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
701 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
702 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
703 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
704 * \sa MEDCouplingUMesh::buildDescendingConnectivity
706 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
709 if(getMeshDimension()!=3)
710 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
711 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
715 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
716 * this->getMeshDimension(), that bound cells of \a this mesh. In
717 * addition arrays describing correspondence between cells of \a this and the result
718 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
719 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
720 * mesh. This method differs from buildDescendingConnectivity() in that apart
721 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
722 * result meshes. So a positive id means that order of nodes in corresponding cells
723 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
724 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
725 * i.e. cell ids are one-based.
726 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
727 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
728 * \warning For speed reasons, this method does not check if node ids in the nodal
729 * connectivity correspond to the size of node coordinates array.
730 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
731 * to write this mesh to the MED file, its cells must be sorted using
732 * sortCellsInMEDFileFrmt().
733 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
734 * each cell of \a this mesh.
735 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
736 * dividing cell ids in \a desc into groups each referring to one
737 * cell of \a this mesh. Its every element (except the last one) is an index
738 * pointing to the first id of a group of cells. For example cells of the
739 * result mesh bounding the cell #1 of \a this mesh are described by following
741 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
742 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
743 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
744 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
745 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
746 * by each cell of the result mesh.
747 * \param [in,out] revDescIndx - the array, of length one more than number of cells
748 * in the result mesh,
749 * dividing cell ids in \a revDesc into groups each referring to one
750 * cell of the result mesh the same way as \a descIndx divides \a desc.
751 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
752 * shares the node coordinates array with \a this mesh. The caller is to
753 * delete this mesh using decrRef() as it is no more needed.
754 * \throw If the coordinates array is not set.
755 * \throw If the nodal connectivity of cells is node defined.
756 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
757 * revDescIndx == NULL.
759 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
760 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
761 * \sa buildDescendingConnectivity()
763 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
765 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
769 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
770 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
771 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
772 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
774 * \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
775 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
776 * \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.
778 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
780 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
781 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
782 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
784 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
786 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
790 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
791 * 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,
792 * excluding a set of meshdim-1 cells in input descending connectivity.
793 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
794 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
795 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
797 * \param [in] desc descending connectivity array.
798 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
799 * \param [in] revDesc reverse descending connectivity array.
800 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
801 * \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
802 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
803 * \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.
805 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
806 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
808 if(!desc || !descIndx || !revDesc || !revDescIndx)
809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
810 const int *descPtr=desc->getConstPointer();
811 const int *descIPtr=descIndx->getConstPointer();
812 const int *revDescPtr=revDesc->getConstPointer();
813 const int *revDescIPtr=revDescIndx->getConstPointer();
815 int nbCells=descIndx->getNumberOfTuples()-1;
816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
818 int *out1Ptr=out1->getPointer();
820 out0->reserve(desc->getNumberOfTuples());
821 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
823 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
825 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
827 out0->insertAtTheEnd(s.begin(),s.end());
829 *out1Ptr=out0->getNumberOfTuples();
831 neighbors=out0.retn();
832 neighborsIndx=out1.retn();
838 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
839 * For speed reasons no check of this will be done.
841 template<class SonsGenerator>
842 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
844 if(!desc || !descIndx || !revDesc || !revDescIndx)
845 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
846 checkConnectivityFullyDefined();
847 int nbOfCells=getNumberOfCells();
848 int nbOfNodes=getNumberOfNodes();
849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
850 int *revNodalIndxPtr=revNodalIndx->getPointer();
851 const int *conn=_nodal_connec->getConstPointer();
852 const int *connIndex=_nodal_connec_index->getConstPointer();
853 std::string name="Mesh constituent of "; name+=getName();
854 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
855 ret->setCoords(getCoords());
856 ret->allocateCells(2*nbOfCells);
857 descIndx->alloc(nbOfCells+1,1);
858 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
859 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
860 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
862 int pos=connIndex[eltId];
863 int posP1=connIndex[eltId+1];
864 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
865 SonsGenerator sg(cm);
866 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
867 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
868 for(unsigned i=0;i<nbOfSons;i++)
870 INTERP_KERNEL::NormalizedCellType cmsId;
871 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
872 for(unsigned k=0;k<nbOfNodesSon;k++)
874 revNodalIndxPtr[tmp[k]+1]++;
875 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
876 revDesc2->pushBackSilent(eltId);
878 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
880 int nbOfCellsM1=ret->getNumberOfCells();
881 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
883 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
884 int *revNodalPtr=revNodal->getPointer();
885 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
886 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
887 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
889 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
890 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
891 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
892 if(*iter>=0)//for polyhedrons
893 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
896 DataArrayInt *commonCells=0,*commonCellsI=0;
897 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
899 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
900 int newNbOfCellsM1=-1;
901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
902 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
903 std::vector<bool> isImpacted(nbOfCellsM1,false);
904 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
905 for(int work2=work[0];work2!=work[1];work2++)
906 isImpacted[commonCellsPtr[work2]]=true;
907 const int *o2nM1Ptr=o2nM1->getConstPointer();
908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
909 const int *n2oM1Ptr=n2oM1->getConstPointer();
910 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
911 ret2->copyTinyInfoFrom(this);
912 desc->alloc(descIndx->back(),1);
913 int *descPtr=desc->getPointer();
914 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
915 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
918 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
921 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
923 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
924 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
927 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
930 revDesc->reserve(newNbOfCellsM1);
931 revDescIndx->alloc(newNbOfCellsM1+1,1);
932 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
933 const int *revDesc2Ptr=revDesc2->getConstPointer();
934 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
936 int oldCellIdM1=n2oM1Ptr[i];
937 if(!isImpacted[oldCellIdM1])
939 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
940 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
944 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
945 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
946 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
954 struct MEDCouplingAccVisit
956 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
957 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
958 int _new_nb_of_nodes;
964 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
965 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
966 * array of cell ids. Pay attention that after conversion all algorithms work slower
967 * with \a this mesh than before conversion. <br> If an exception is thrown during the
968 * conversion due presence of invalid ids in the array of cells to convert, as a
969 * result \a this mesh contains some already converted elements. In this case the 2D
970 * mesh remains valid but 3D mesh becomes \b inconsistent!
971 * \warning This method can significantly modify the order of geometric types in \a this,
972 * hence, to write this mesh to the MED file, its cells must be sorted using
973 * sortCellsInMEDFileFrmt().
974 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
975 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
976 * cellIdsToConvertBg.
977 * \throw If the coordinates array is not set.
978 * \throw If the nodal connectivity of cells is node defined.
979 * \throw If dimension of \a this mesh is not either 2 or 3.
981 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
982 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
984 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
987 int dim=getMeshDimension();
989 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
990 int nbOfCells=getNumberOfCells();
993 const int *connIndex=_nodal_connec_index->getConstPointer();
994 int *conn=_nodal_connec->getPointer();
995 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
997 if(*iter>=0 && *iter<nbOfCells)
999 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1000 if(!cm.isQuadratic())
1001 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1003 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1007 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1008 oss << " in range [0," << nbOfCells << ") !";
1009 throw INTERP_KERNEL::Exception(oss.str().c_str());
1015 int *connIndex=_nodal_connec_index->getPointer();
1016 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1017 const int *connOld=_nodal_connec->getConstPointer();
1018 int connOldLgth=_nodal_connec->getNbOfElems();
1019 std::vector<int> connNew(connOld,connOld+connOldLgth);
1020 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1022 if(*iter>=0 && *iter<nbOfCells)
1024 int pos=connIndex[*iter];
1025 int posP1=connIndex[(*iter)+1];
1026 int lgthOld=posP1-pos-1;
1027 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1028 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1029 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1030 int *tmp=new int[nbOfFaces*lgthOld];
1032 for(int j=0;j<(int)nbOfFaces;j++)
1034 INTERP_KERNEL::NormalizedCellType type;
1035 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1039 std::size_t newLgth=std::distance(tmp,work)-1;
1040 std::size_t delta=newLgth-lgthOld;
1041 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1042 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1043 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1048 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1049 oss << " in range [0," << nbOfCells << ") !";
1050 throw INTERP_KERNEL::Exception(oss.str().c_str());
1053 _nodal_connec->alloc((int)connNew.size(),1);
1054 int *newConnPtr=_nodal_connec->getPointer();
1055 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1061 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1062 * polyhedrons (if \a this is a 3D mesh).
1063 * \warning As this method is purely for user-friendliness and no optimization is
1064 * done to avoid construction of a useless vector, this method can be costly
1066 * \throw If the coordinates array is not set.
1067 * \throw If the nodal connectivity of cells is node defined.
1068 * \throw If dimension of \a this mesh is not either 2 or 3.
1070 void MEDCouplingUMesh::convertAllToPoly()
1072 int nbOfCells=getNumberOfCells();
1073 std::vector<int> cellIds(nbOfCells);
1074 for(int i=0;i<nbOfCells;i++)
1076 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1080 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1081 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1082 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1083 * base facet of the volume and the second half of nodes describes an opposite facet
1084 * having the same number of nodes as the base one. This method converts such
1085 * connectivity to a valid polyhedral format where connectivity of each facet is
1086 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1087 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1088 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1089 * a correct orientation of the first facet of a polyhedron, else orientation of a
1090 * corrected cell is reverse.<br>
1091 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1092 * it releases the user from boring description of polyhedra connectivity in the valid
1094 * \throw If \a this->getMeshDimension() != 3.
1095 * \throw If \a this->getSpaceDimension() != 3.
1096 * \throw If the nodal connectivity of cells is not defined.
1097 * \throw If the coordinates array is not set.
1098 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1099 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1101 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1102 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1104 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1106 checkFullyDefined();
1107 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1108 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1109 int nbOfCells=getNumberOfCells();
1110 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1111 newCi->alloc(nbOfCells+1,1);
1112 int *newci=newCi->getPointer();
1113 const int *ci=_nodal_connec_index->getConstPointer();
1114 const int *c=_nodal_connec->getConstPointer();
1116 for(int i=0;i<nbOfCells;i++)
1118 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1119 if(type==INTERP_KERNEL::NORM_POLYHED)
1121 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1123 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1124 throw INTERP_KERNEL::Exception(oss.str().c_str());
1126 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1129 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 !";
1130 throw INTERP_KERNEL::Exception(oss.str().c_str());
1133 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)
1136 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1139 newC->alloc(newci[nbOfCells],1);
1140 int *newc=newC->getPointer();
1141 for(int i=0;i<nbOfCells;i++)
1143 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1144 if(type==INTERP_KERNEL::NORM_POLYHED)
1146 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1147 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1149 for(std::size_t j=0;j<n1;j++)
1151 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1153 newc[n1+5*j+1]=c[ci[i]+1+j];
1154 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1155 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1156 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1161 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1163 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1164 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1169 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1170 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1171 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1172 * to write this mesh to the MED file, its cells must be sorted using
1173 * sortCellsInMEDFileFrmt().
1174 * \return \c true if at least one cell has been converted, \c false else. In the
1175 * last case the nodal connectivity remains unchanged.
1176 * \throw If the coordinates array is not set.
1177 * \throw If the nodal connectivity of cells is not defined.
1178 * \throw If \a this->getMeshDimension() < 0.
1180 bool MEDCouplingUMesh::unPolyze()
1182 checkFullyDefined();
1183 int mdim=getMeshDimension();
1185 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1188 int nbOfCells=getNumberOfCells();
1191 int initMeshLgth=getMeshLength();
1192 int *conn=_nodal_connec->getPointer();
1193 int *index=_nodal_connec_index->getPointer();
1198 for(int i=0;i<nbOfCells;i++)
1200 lgthOfCurCell=index[i+1]-posOfCurCell;
1201 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1202 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1203 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1207 switch(cm.getDimension())
1211 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1212 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1213 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1218 int nbOfFaces,lgthOfPolyhConn;
1219 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1220 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1225 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1229 ret=ret || (newType!=type);
1230 conn[newPos]=newType;
1232 posOfCurCell=index[i+1];
1237 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1238 newPos+=lgthOfCurCell;
1239 posOfCurCell+=lgthOfCurCell;
1243 if(newPos!=initMeshLgth)
1244 _nodal_connec->reAlloc(newPos);
1251 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1252 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1253 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1255 * \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
1258 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1260 checkFullyDefined();
1261 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1262 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1263 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1264 coords->recenterForMaxPrecision(eps);
1266 int nbOfCells=getNumberOfCells();
1267 const int *conn=_nodal_connec->getConstPointer();
1268 const int *index=_nodal_connec_index->getConstPointer();
1269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1270 connINew->alloc(nbOfCells+1,1);
1271 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1274 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1276 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1278 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1282 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1283 *connINewPtr=connNew->getNumberOfTuples();
1286 setConnectivity(connNew,connINew,false);
1290 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1291 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1292 * the format of returned DataArrayInt instance.
1294 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1295 * \sa MEDCouplingUMesh::getNodeIdsInUse
1297 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1299 checkConnectivityFullyDefined();
1300 int nbOfCells=getNumberOfCells();
1301 const int *connIndex=_nodal_connec_index->getConstPointer();
1302 const int *conn=_nodal_connec->getConstPointer();
1303 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1304 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1305 std::vector<bool> retS(maxElt,false);
1306 for(int i=0;i<nbOfCells;i++)
1307 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1311 for(int i=0;i<maxElt;i++)
1314 DataArrayInt *ret=DataArrayInt::New();
1316 int *retPtr=ret->getPointer();
1317 for(int i=0;i<maxElt;i++)
1324 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1325 * \sa MEDCouplingUMesh::getNodeIdsInUse
1327 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1329 int nbOfNodes=(int)nodeIdsInUse.size();
1330 int nbOfCells=getNumberOfCells();
1331 const int *connIndex=_nodal_connec_index->getConstPointer();
1332 const int *conn=_nodal_connec->getConstPointer();
1333 for(int i=0;i<nbOfCells;i++)
1334 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1337 if(conn[j]<nbOfNodes)
1338 nodeIdsInUse[conn[j]]=true;
1341 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1342 throw INTERP_KERNEL::Exception(oss.str().c_str());
1348 * Finds nodes not used in any cell and returns an array giving a new id to every node
1349 * by excluding the unused nodes, for which the array holds -1. The result array is
1350 * a mapping in "Old to New" mode.
1351 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1352 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1353 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1354 * if the node is unused or a new id else. The caller is to delete this
1355 * array using decrRef() as it is no more needed.
1356 * \throw If the coordinates array is not set.
1357 * \throw If the nodal connectivity of cells is not defined.
1358 * \throw If the nodal connectivity includes an invalid id.
1360 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1361 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1362 * \sa computeNodeIdsAlg()
1364 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1367 int nbOfNodes=getNumberOfNodes();
1368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1369 ret->alloc(nbOfNodes,1);
1370 int *traducer=ret->getPointer();
1371 std::fill(traducer,traducer+nbOfNodes,-1);
1372 int nbOfCells=getNumberOfCells();
1373 const int *connIndex=_nodal_connec_index->getConstPointer();
1374 const int *conn=_nodal_connec->getConstPointer();
1375 for(int i=0;i<nbOfCells;i++)
1376 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1379 if(conn[j]<nbOfNodes)
1380 traducer[conn[j]]=1;
1383 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1384 throw INTERP_KERNEL::Exception(oss.str().c_str());
1387 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1388 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1393 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1394 * For each cell in \b this the number of nodes constituting cell is computed.
1395 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1396 * So for pohyhedrons some nodes can be counted several times in the returned result.
1398 * \return a newly allocated array
1399 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1401 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1403 checkConnectivityFullyDefined();
1404 int nbOfCells=getNumberOfCells();
1405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1406 ret->alloc(nbOfCells,1);
1407 int *retPtr=ret->getPointer();
1408 const int *conn=getNodalConnectivity()->getConstPointer();
1409 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1410 for(int i=0;i<nbOfCells;i++,retPtr++)
1412 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1413 *retPtr=connI[i+1]-connI[i]-1;
1415 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1421 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1422 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1424 * \return DataArrayInt * - new object to be deallocated by the caller.
1425 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1427 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1429 checkConnectivityFullyDefined();
1430 int nbOfCells=getNumberOfCells();
1431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1432 ret->alloc(nbOfCells,1);
1433 int *retPtr=ret->getPointer();
1434 const int *conn=getNodalConnectivity()->getConstPointer();
1435 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1436 for(int i=0;i<nbOfCells;i++,retPtr++)
1438 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1439 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1440 *retPtr=(int)s.size();
1444 *retPtr=(int)s.size();
1451 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1452 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1454 * \return a newly allocated array
1456 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1458 checkConnectivityFullyDefined();
1459 int nbOfCells=getNumberOfCells();
1460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1461 ret->alloc(nbOfCells,1);
1462 int *retPtr=ret->getPointer();
1463 const int *conn=getNodalConnectivity()->getConstPointer();
1464 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1465 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1467 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1468 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1474 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1475 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1476 * array mean that the corresponding old node is no more used.
1477 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1478 * this->getNumberOfNodes() before call of this method. The caller is to
1479 * delete this array using decrRef() as it is no more needed.
1480 * \throw If the coordinates array is not set.
1481 * \throw If the nodal connectivity of cells is not defined.
1482 * \throw If the nodal connectivity includes an invalid id.
1484 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1485 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1487 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1489 return MEDCouplingPointSet::zipCoordsTraducer();
1493 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1494 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1496 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1501 return AreCellsEqual0(conn,connI,cell1,cell2);
1503 return AreCellsEqual1(conn,connI,cell1,cell2);
1505 return AreCellsEqual2(conn,connI,cell1,cell2);
1507 return AreCellsEqual3(conn,connI,cell1,cell2);
1509 return AreCellsEqual7(conn,connI,cell1,cell2);
1511 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1515 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1517 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1519 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1520 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1525 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1527 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1529 int sz=connI[cell1+1]-connI[cell1];
1530 if(sz==connI[cell2+1]-connI[cell2])
1532 if(conn[connI[cell1]]==conn[connI[cell2]])
1534 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1535 unsigned dim=cm.getDimension();
1541 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1542 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1543 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1544 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1545 return work!=tmp+sz1?1:0;
1548 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1551 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1558 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1560 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1562 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1564 if(conn[connI[cell1]]==conn[connI[cell2]])
1566 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1567 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1575 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1577 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1579 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1581 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1582 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1589 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1591 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1593 int sz=connI[cell1+1]-connI[cell1];
1594 if(sz==connI[cell2+1]-connI[cell2])
1596 if(conn[connI[cell1]]==conn[connI[cell2]])
1598 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1599 unsigned dim=cm.getDimension();
1605 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1606 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1607 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1608 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1613 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1614 std::reverse_iterator<int *> it2((int *)tmp);
1615 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1621 return work!=tmp+sz1?1:0;
1624 {//case of SEG2 and SEG3
1625 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1627 if(!cm.isQuadratic())
1629 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1630 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1631 if(std::equal(it1,it2,conn+connI[cell2]+1))
1637 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])
1644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1651 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1652 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1653 * and result remains unchanged.
1654 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1655 * If in 'candidates' pool -1 value is considered as an empty value.
1656 * WARNING this method returns only ONE set of result !
1658 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1660 if(candidates.size()<1)
1663 std::vector<int>::const_iterator iter=candidates.begin();
1664 int start=(*iter++);
1665 for(;iter!=candidates.end();iter++)
1667 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1672 result->pushBackSilent(start);
1676 result->pushBackSilent(*iter);
1678 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1685 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1686 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1688 * \param [in] compType input specifying the technique used to compare cells each other.
1689 * - 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.
1690 * - 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)
1691 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1692 * - 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
1693 * can be used for users not sensitive to orientation of cell
1694 * \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.
1695 * \param [out] commonCells
1696 * \param [out] commonCellsI
1697 * \return the correspondance array old to new in a newly allocated array.
1700 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1702 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1703 getReverseNodalConnectivity(revNodal,revNodalI);
1704 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1707 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1708 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1711 int nbOfCells=nodalI->getNumberOfTuples()-1;
1712 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1713 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1714 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1715 std::vector<bool> isFetched(nbOfCells,false);
1718 for(int i=0;i<nbOfCells;i++)
1722 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1723 std::vector<int> v,v2;
1724 if(connOfNode!=connPtr+connIPtr[i+1])
1726 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1727 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1730 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1734 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1735 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1736 v2.resize(std::distance(v2.begin(),it));
1740 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1742 int pos=commonCellsI->back();
1743 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1744 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1745 isFetched[*it]=true;
1753 for(int i=startCellId;i<nbOfCells;i++)
1757 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1758 std::vector<int> v,v2;
1759 if(connOfNode!=connPtr+connIPtr[i+1])
1761 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1764 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1768 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1769 v2.resize(std::distance(v2.begin(),it));
1773 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1775 int pos=commonCellsI->back();
1776 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1777 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1778 isFetched[*it]=true;
1784 commonCellsArr=commonCells.retn();
1785 commonCellsIArr=commonCellsI.retn();
1789 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1790 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1791 * than \a other->getNumberOfCells() in the returned array means that there is no
1792 * corresponding cell in \a this mesh.
1793 * It is expected that \a this and \a other meshes share the same node coordinates
1794 * array, if it is not so an exception is thrown.
1795 * \param [in] other - the mesh to compare with.
1796 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1797 * valid values [0,1,2], see zipConnectivityTraducer().
1798 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1799 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1800 * values. The caller is to delete this array using
1801 * decrRef() as it is no more needed.
1802 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1805 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1806 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1807 * \sa checkDeepEquivalOnSameNodesWith()
1808 * \sa checkGeoEquivalWith()
1810 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1812 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1813 int nbOfCells=getNumberOfCells();
1814 static const int possibleCompType[]={0,1,2};
1815 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1817 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1818 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1820 throw INTERP_KERNEL::Exception(oss.str().c_str());
1822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1823 arr=o2n->substr(nbOfCells);
1824 arr->setName(other->getName().c_str());
1826 if(other->getNumberOfCells()==0)
1828 return arr->getMaxValue(tmp)<nbOfCells;
1832 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1833 * This method tries to determine if \b other is fully included in \b this.
1834 * The main difference is that this method is not expected to throw exception.
1835 * This method has two outputs :
1837 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1838 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1840 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1842 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1843 DataArrayInt *commonCells=0,*commonCellsI=0;
1844 int thisNbCells=getNumberOfCells();
1845 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1847 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1848 int otherNbCells=other->getNumberOfCells();
1849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1850 arr2->alloc(otherNbCells,1);
1851 arr2->fillWithZero();
1852 int *arr2Ptr=arr2->getPointer();
1853 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1854 for(int i=0;i<nbOfCommon;i++)
1856 int start=commonCellsPtr[commonCellsIPtr[i]];
1857 if(start<thisNbCells)
1859 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1861 int sig=commonCellsPtr[j]>0?1:-1;
1862 int val=std::abs(commonCellsPtr[j])-1;
1863 if(val>=thisNbCells)
1864 arr2Ptr[val-thisNbCells]=sig*(start+1);
1868 arr2->setName(other->getName().c_str());
1869 if(arr2->presenceOfValue(0))
1875 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1879 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1881 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1882 std::vector<const MEDCouplingUMesh *> ms(2);
1885 return MergeUMeshesOnSameCoords(ms);
1889 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1890 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1891 * cellIds is not given explicitely but by a range python like.
1893 * \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.
1894 * \return a newly allocated
1896 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1897 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1899 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1901 if(getMeshDimension()!=-1)
1902 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1905 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1907 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1909 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1911 return const_cast<MEDCouplingUMesh *>(this);
1916 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1917 * The result mesh shares or not the node coordinates array with \a this mesh depending
1918 * on \a keepCoords parameter.
1919 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1920 * to write this mesh to the MED file, its cells must be sorted using
1921 * sortCellsInMEDFileFrmt().
1922 * \param [in] begin - an array of cell ids to include to the new mesh.
1923 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1924 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1925 * array of \a this mesh, else "free" nodes are removed from the result mesh
1926 * by calling zipCoords().
1927 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1928 * to delete this mesh using decrRef() as it is no more needed.
1929 * \throw If the coordinates array is not set.
1930 * \throw If the nodal connectivity of cells is not defined.
1931 * \throw If any cell id in the array \a begin is not valid.
1933 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1934 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1936 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1938 if(getMeshDimension()!=-1)
1939 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1943 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1945 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1947 return const_cast<MEDCouplingUMesh *>(this);
1952 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1954 * 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.
1955 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1956 * The number of cells of \b this will remain the same with this method.
1958 * \param [in] begin begin of cell ids (included) of cells in this to assign
1959 * \param [in] end end of cell ids (excluded) of cells in this to assign
1960 * \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 ).
1961 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1963 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1965 checkConnectivityFullyDefined();
1966 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1967 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1968 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1969 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1971 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1972 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1973 throw INTERP_KERNEL::Exception(oss.str().c_str());
1975 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1976 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1978 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1979 throw INTERP_KERNEL::Exception(oss.str().c_str());
1981 int nbOfCells=getNumberOfCells();
1982 bool easyAssign=true;
1983 const int *connI=_nodal_connec_index->getConstPointer();
1984 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1985 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1987 if(*it>=0 && *it<nbOfCells)
1989 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1993 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1994 throw INTERP_KERNEL::Exception(oss.str().c_str());
1999 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2004 DataArrayInt *arrOut=0,*arrIOut=0;
2005 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2007 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2008 setConnectivity(arrOut,arrIOut,true);
2012 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2014 checkConnectivityFullyDefined();
2015 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2016 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2017 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2018 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2020 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2021 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2022 throw INTERP_KERNEL::Exception(oss.str().c_str());
2024 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2025 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2027 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2028 throw INTERP_KERNEL::Exception(oss.str().c_str());
2030 int nbOfCells=getNumberOfCells();
2031 bool easyAssign=true;
2032 const int *connI=_nodal_connec_index->getConstPointer();
2033 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2035 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2037 if(it>=0 && it<nbOfCells)
2039 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2043 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2044 throw INTERP_KERNEL::Exception(oss.str().c_str());
2049 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2054 DataArrayInt *arrOut=0,*arrIOut=0;
2055 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2058 setConnectivity(arrOut,arrIOut,true);
2063 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2064 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2065 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2066 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2068 * \param [in] begin input start of array of node ids.
2069 * \param [in] end input end of array of node ids.
2070 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2071 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2073 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2075 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2076 checkConnectivityFullyDefined();
2078 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2079 std::vector<bool> fastFinder(sz,false);
2080 for(const int *work=begin;work!=end;work++)
2081 if(*work>=0 && *work<sz)
2082 fastFinder[*work]=true;
2083 int nbOfCells=getNumberOfCells();
2084 const int *conn=getNodalConnectivity()->getConstPointer();
2085 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2086 for(int i=0;i<nbOfCells;i++)
2088 int ref=0,nbOfHit=0;
2089 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2093 if(fastFinder[*work2])
2096 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2097 cellIdsKept->pushBackSilent(i);
2099 cellIdsKeptArr=cellIdsKept.retn();
2103 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2104 * this->getMeshDimension(), that bound some cells of \a this mesh.
2105 * The cells of lower dimension to include to the result mesh are selected basing on
2106 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2107 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2108 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2109 * created mesh shares the node coordinates array with \a this mesh.
2110 * \param [in] begin - the array of node ids.
2111 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2112 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2113 * array \a begin are added, else cells whose any node is in the
2114 * array \a begin are added.
2115 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2116 * to delete this mesh using decrRef() as it is no more needed.
2117 * \throw If the coordinates array is not set.
2118 * \throw If the nodal connectivity of cells is not defined.
2119 * \throw If any node id in \a begin is not valid.
2121 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2122 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2124 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2127 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2128 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2129 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2130 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2134 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2135 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2136 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2137 * array of \a this mesh, else "free" nodes are removed from the result mesh
2138 * by calling zipCoords().
2139 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2140 * to delete this mesh using decrRef() as it is no more needed.
2141 * \throw If the coordinates array is not set.
2142 * \throw If the nodal connectivity of cells is not defined.
2144 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2145 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2147 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2149 DataArrayInt *desc=DataArrayInt::New();
2150 DataArrayInt *descIndx=DataArrayInt::New();
2151 DataArrayInt *revDesc=DataArrayInt::New();
2152 DataArrayInt *revDescIndx=DataArrayInt::New();
2154 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2157 descIndx->decrRef();
2158 int nbOfCells=meshDM1->getNumberOfCells();
2159 const int *revDescIndxC=revDescIndx->getConstPointer();
2160 std::vector<int> boundaryCells;
2161 for(int i=0;i<nbOfCells;i++)
2162 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2163 boundaryCells.push_back(i);
2164 revDescIndx->decrRef();
2165 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2170 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2171 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2172 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2174 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2176 checkFullyDefined();
2177 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2182 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2183 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2187 const int *revDescPtr=revDesc->getConstPointer();
2188 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2189 int nbOfCells=getNumberOfCells();
2190 std::vector<bool> ret1(nbOfCells,false);
2192 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2193 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2194 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2196 DataArrayInt *ret2=DataArrayInt::New();
2198 int *ret2Ptr=ret2->getPointer();
2200 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2203 ret2->setName("BoundaryCells");
2208 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2209 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2210 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2211 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2213 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2214 * This method method returns cells ids set s = s1 + s2 where :
2216 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2217 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2219 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2220 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2222 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2223 * \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
2224 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2226 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2228 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2229 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2230 checkConnectivityFullyDefined();
2231 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2232 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2233 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2234 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2236 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2238 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2239 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2240 DataArrayInt *idsOtherInConsti=0;
2241 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2244 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2246 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2247 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2250 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2251 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2253 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2254 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2255 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2256 neighThisPartAuto=0;
2257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2258 const int li[2]={0,1};
2259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2260 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2264 cellIdsRk0=s0arr.retn();
2265 cellIdsRk1=s_renum1.retn();
2269 * 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
2270 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2272 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2274 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2281 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2282 revDesc=0; desc=0; descIndx=0;
2283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2285 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2289 * Finds nodes lying on the boundary of \a this mesh.
2290 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2291 * nodes. The caller is to delete this array using decrRef() as it is no
2293 * \throw If the coordinates array is not set.
2294 * \throw If the nodal connectivity of cells is node defined.
2296 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2297 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2299 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2301 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2302 return skin->computeFetchedNodeIds();
2305 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2308 return const_cast<MEDCouplingUMesh *>(this);
2312 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2313 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2314 * 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.
2315 * 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.
2316 * 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.
2318 * \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
2319 * parameter is altered during the call.
2320 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2321 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2322 * \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.
2324 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2326 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2327 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2329 checkFullyDefined();
2330 otherDimM1OnSameCoords.checkFullyDefined();
2331 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2332 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2333 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2334 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2335 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2336 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2339 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2340 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2344 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2348 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2349 DataArrayInt *idsTmp=0;
2350 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2354 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2355 DataArrayInt *tmp0=0,*tmp1=0;
2356 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2361 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2362 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2364 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2365 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2366 nodeIdsToDuplicate=s3.retn();
2370 * This method operates a modification of the connectivity and coords in \b this.
2371 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2372 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2373 * 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
2374 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2375 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2377 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2379 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2380 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2382 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2384 int nbOfNodes=getNumberOfNodes();
2385 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2386 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2390 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2391 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2392 * This method is a generalization of shiftNodeNumbersInConn().
2393 * \warning This method performs no check of validity of new ids. **Use it with care !**
2394 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2395 * this->getNumberOfNodes(), in "Old to New" mode.
2396 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2397 * \throw If the nodal connectivity of cells is not defined.
2399 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2400 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2402 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2404 checkConnectivityFullyDefined();
2405 int *conn=getNodalConnectivity()->getPointer();
2406 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2407 int nbOfCells=getNumberOfCells();
2408 for(int i=0;i<nbOfCells;i++)
2409 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2411 int& node=conn[iconn];
2412 if(node>=0)//avoid polyhedron separator
2414 node=newNodeNumbersO2N[node];
2417 _nodal_connec->declareAsNew();
2422 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2423 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2424 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2426 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2428 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2430 checkConnectivityFullyDefined();
2431 int *conn=getNodalConnectivity()->getPointer();
2432 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2433 int nbOfCells=getNumberOfCells();
2434 for(int i=0;i<nbOfCells;i++)
2435 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2437 int& node=conn[iconn];
2438 if(node>=0)//avoid polyhedron separator
2443 _nodal_connec->declareAsNew();
2448 * This method operates a modification of the connectivity in \b this.
2449 * 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.
2450 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2451 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2452 * 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
2453 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2454 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2456 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2457 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2459 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2460 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2461 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2463 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2465 checkConnectivityFullyDefined();
2466 std::map<int,int> m;
2468 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2470 int *conn=getNodalConnectivity()->getPointer();
2471 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2472 int nbOfCells=getNumberOfCells();
2473 for(int i=0;i<nbOfCells;i++)
2474 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2476 int& node=conn[iconn];
2477 if(node>=0)//avoid polyhedron separator
2479 std::map<int,int>::iterator it=m.find(node);
2488 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2490 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2491 * After the call of this method the number of cells remains the same as before.
2493 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2494 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2495 * be strictly in [0;this->getNumberOfCells()).
2497 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2498 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2499 * should be contained in[0;this->getNumberOfCells()).
2501 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2503 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2505 checkConnectivityFullyDefined();
2506 int nbCells=getNumberOfCells();
2507 const int *array=old2NewBg;
2509 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2511 const int *conn=_nodal_connec->getConstPointer();
2512 const int *connI=_nodal_connec_index->getConstPointer();
2513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2515 const int *n2oPtr=n2o->begin();
2516 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2517 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2518 newConn->copyStringInfoFrom(*_nodal_connec);
2519 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2520 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2521 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2523 int *newC=newConn->getPointer();
2524 int *newCI=newConnI->getPointer();
2527 for(int i=0;i<nbCells;i++)
2530 int nbOfElts=connI[pos+1]-connI[pos];
2531 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2536 setConnectivity(newConn,newConnI);
2538 free(const_cast<int *>(array));
2542 * Finds cells whose bounding boxes intersect a given bounding box.
2543 * \param [in] bbox - an array defining the bounding box via coordinates of its
2544 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2546 * \param [in] eps - a factor used to increase size of the bounding box of cell
2547 * before comparing it with \a bbox. This factor is multiplied by the maximal
2548 * extent of the bounding box of cell to produce an addition to this bounding box.
2549 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2550 * cells. The caller is to delete this array using decrRef() as it is no more
2552 * \throw If the coordinates array is not set.
2553 * \throw If the nodal connectivity of cells is not defined.
2555 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2556 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2558 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2561 if(getMeshDimension()==-1)
2563 elems->pushBackSilent(0);
2564 return elems.retn();
2566 int dim=getSpaceDimension();
2567 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2568 const int* conn = getNodalConnectivity()->getConstPointer();
2569 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2570 const double* coords = getCoords()->getConstPointer();
2571 int nbOfCells=getNumberOfCells();
2572 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2574 for (int i=0; i<dim; i++)
2576 elem_bb[i*2]=std::numeric_limits<double>::max();
2577 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2580 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2582 int node= conn[inode];
2583 if(node>=0)//avoid polyhedron separator
2585 for (int idim=0; idim<dim; idim++)
2587 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2589 elem_bb[idim*2] = coords[node*dim+idim] ;
2591 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2593 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2598 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2599 elems->pushBackSilent(ielem);
2601 return elems.retn();
2605 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2606 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2607 * added in 'elems' parameter.
2609 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2612 if(getMeshDimension()==-1)
2614 elems->pushBackSilent(0);
2615 return elems.retn();
2617 int dim=getSpaceDimension();
2618 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2619 const int* conn = getNodalConnectivity()->getConstPointer();
2620 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2621 const double* coords = getCoords()->getConstPointer();
2622 int nbOfCells=getNumberOfCells();
2623 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2625 for (int i=0; i<dim; i++)
2627 elem_bb[i*2]=std::numeric_limits<double>::max();
2628 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2631 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2633 int node= conn[inode];
2634 if(node>=0)//avoid polyhedron separator
2636 for (int idim=0; idim<dim; idim++)
2638 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2640 elem_bb[idim*2] = coords[node*dim+idim] ;
2642 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2644 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2649 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2650 elems->pushBackSilent(ielem);
2652 return elems.retn();
2656 * Returns a type of a cell by its id.
2657 * \param [in] cellId - the id of the cell of interest.
2658 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2659 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2661 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2663 const int *ptI=_nodal_connec_index->getConstPointer();
2664 const int *pt=_nodal_connec->getConstPointer();
2665 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2666 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2669 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2670 throw INTERP_KERNEL::Exception(oss.str().c_str());
2675 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2676 * This method does not throw exception if geometric type \a type is not in \a this.
2677 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2678 * The coordinates array is not considered here.
2680 * \param [in] type the geometric type
2681 * \return cell ids in this having geometric type \a type.
2683 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2688 checkConnectivityFullyDefined();
2689 int nbCells=getNumberOfCells();
2690 int mdim=getMeshDimension();
2691 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2692 if(mdim!=(int)cm.getDimension())
2693 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2694 const int *ptI=_nodal_connec_index->getConstPointer();
2695 const int *pt=_nodal_connec->getConstPointer();
2696 for(int i=0;i<nbCells;i++)
2698 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2699 ret->pushBackSilent(i);
2705 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2707 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2709 const int *ptI=_nodal_connec_index->getConstPointer();
2710 const int *pt=_nodal_connec->getConstPointer();
2711 int nbOfCells=getNumberOfCells();
2713 for(int i=0;i<nbOfCells;i++)
2714 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2720 * Returns the nodal connectivity of a given cell.
2721 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2722 * all returned node ids can be used in getCoordinatesOfNode().
2723 * \param [in] cellId - an id of the cell of interest.
2724 * \param [in,out] conn - a vector where the node ids are appended. It is not
2725 * cleared before the appending.
2726 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2728 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2730 const int *ptI=_nodal_connec_index->getConstPointer();
2731 const int *pt=_nodal_connec->getConstPointer();
2732 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2737 std::string MEDCouplingUMesh::simpleRepr() const
2739 static const char msg0[]="No coordinates specified !";
2740 std::ostringstream ret;
2741 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2742 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2744 double tt=getTime(tmpp1,tmpp2);
2745 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2746 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2748 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2750 { ret << " Mesh dimension has not been set or is invalid !"; }
2753 const int spaceDim=getSpaceDimension();
2754 ret << spaceDim << "\nInfo attached on space dimension : ";
2755 for(int i=0;i<spaceDim;i++)
2756 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2760 ret << msg0 << "\n";
2761 ret << "Number of nodes : ";
2763 ret << getNumberOfNodes() << "\n";
2765 ret << msg0 << "\n";
2766 ret << "Number of cells : ";
2767 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2768 ret << getNumberOfCells() << "\n";
2770 ret << "No connectivity specified !" << "\n";
2771 ret << "Cell types present : ";
2772 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2774 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2775 ret << cm.getRepr() << " ";
2781 std::string MEDCouplingUMesh::advancedRepr() const
2783 std::ostringstream ret;
2784 ret << simpleRepr();
2785 ret << "\nCoordinates array : \n___________________\n\n";
2787 _coords->reprWithoutNameStream(ret);
2789 ret << "No array set !\n";
2790 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2791 reprConnectivityOfThisLL(ret);
2796 * This method returns a C++ code that is a dump of \a this.
2797 * This method will throw if this is not fully defined.
2799 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2801 static const char coordsName[]="coords";
2802 static const char connName[]="conn";
2803 static const char connIName[]="connI";
2804 checkFullyDefined();
2805 std::ostringstream ret; ret << "// coordinates" << std::endl;
2806 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2807 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2808 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2809 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2810 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2811 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2812 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2816 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2818 std::ostringstream ret;
2819 reprConnectivityOfThisLL(ret);
2824 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2825 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2826 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2829 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2830 * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
2831 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2833 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2835 int mdim=getMeshDimension();
2837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2838 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2840 bool needToCpyCT=true;
2843 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2851 if(!_nodal_connec_index)
2853 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2858 tmp2=_nodal_connec_index;
2861 ret->setConnectivity(tmp1,tmp2,false);
2866 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2867 ret->setCoords(coords);
2870 ret->setCoords(_coords);
2874 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2876 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2878 int nbOfCells=getNumberOfCells();
2879 const int *c=_nodal_connec->getConstPointer();
2880 const int *ci=_nodal_connec_index->getConstPointer();
2881 for(int i=0;i<nbOfCells;i++)
2883 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2884 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2885 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2890 stream << "Connectivity not defined !\n";
2893 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2895 const int *ptI=_nodal_connec_index->getConstPointer();
2896 const int *pt=_nodal_connec->getConstPointer();
2897 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2898 return ptI[cellId+1]-ptI[cellId]-1;
2900 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2904 * Returns types of cells of the specified part of \a this mesh.
2905 * This method avoids computing sub-mesh explicitely to get its types.
2906 * \param [in] begin - an array of cell ids of interest.
2907 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2908 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2909 * describing the cell types.
2910 * \throw If the coordinates array is not set.
2911 * \throw If the nodal connectivity of cells is not defined.
2914 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2916 checkFullyDefined();
2917 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2918 const int *conn=_nodal_connec->getConstPointer();
2919 const int *connIndex=_nodal_connec_index->getConstPointer();
2920 for(const int *w=begin;w!=end;w++)
2921 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2926 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2927 * a set of types of cells constituting \a this mesh.
2928 * This method is for advanced users having prepared their connectivity before. For
2929 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2930 * \param [in] conn - the nodal connectivity array.
2931 * \param [in] connIndex - the nodal connectivity index array.
2932 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2935 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2937 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2938 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2939 if(isComputingTypes)
2945 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2946 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2948 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2949 _nodal_connec(0),_nodal_connec_index(0),
2950 _types(other._types)
2952 if(other._nodal_connec)
2953 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2954 if(other._nodal_connec_index)
2955 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2958 MEDCouplingUMesh::~MEDCouplingUMesh()
2961 _nodal_connec->decrRef();
2962 if(_nodal_connec_index)
2963 _nodal_connec_index->decrRef();
2967 * Recomputes a set of cell types of \a this mesh. For more info see
2968 * \ref MEDCouplingUMeshNodalConnectivity.
2970 void MEDCouplingUMesh::computeTypes()
2972 if(_nodal_connec && _nodal_connec_index)
2975 const int *conn=_nodal_connec->getConstPointer();
2976 const int *connIndex=_nodal_connec_index->getConstPointer();
2977 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2979 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2980 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2985 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2987 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2989 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2990 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2994 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2996 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2998 if(!_nodal_connec_index || !_nodal_connec)
2999 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3003 * Returns a number of cells constituting \a this mesh.
3004 * \return int - the number of cells in \a this mesh.
3005 * \throw If the nodal connectivity of cells is not defined.
3007 int MEDCouplingUMesh::getNumberOfCells() const
3009 if(_nodal_connec_index)
3010 return _nodal_connec_index->getNumberOfTuples()-1;
3015 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3019 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3020 * mesh. For more info see \ref MEDCouplingMeshesPage.
3021 * \return int - the dimension of \a this mesh.
3022 * \throw If the mesh dimension is not defined using setMeshDimension().
3024 int MEDCouplingUMesh::getMeshDimension() const
3027 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3032 * Returns a length of the nodal connectivity array.
3033 * This method is for test reason. Normally the integer returned is not useable by
3034 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3035 * \return int - the length of the nodal connectivity array.
3037 int MEDCouplingUMesh::getMeshLength() const
3039 return _nodal_connec->getNbOfElems();
3043 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3045 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3047 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3048 tinyInfo.push_back(getMeshDimension());
3049 tinyInfo.push_back(getNumberOfCells());
3051 tinyInfo.push_back(getMeshLength());
3053 tinyInfo.push_back(-1);
3057 * First step of unserialization process.
3059 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3061 return tinyInfo[6]<=0;
3065 * Second step of serialization process.
3066 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3068 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3070 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3072 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3076 * Third and final step of serialization process.
3078 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3080 MEDCouplingPointSet::serialize(a1,a2);
3081 if(getMeshDimension()>-1)
3083 a1=DataArrayInt::New();
3084 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3085 int *ptA1=a1->getPointer();
3086 const int *conn=getNodalConnectivity()->getConstPointer();
3087 const int *index=getNodalConnectivityIndex()->getConstPointer();
3088 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3089 std::copy(conn,conn+getMeshLength(),ptA1);
3096 * Second and final unserialization process.
3097 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3099 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3101 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3102 setMeshDimension(tinyInfo[5]);
3106 const int *recvBuffer=a1->getConstPointer();
3107 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3108 myConnecIndex->alloc(tinyInfo[6]+1,1);
3109 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3110 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3111 myConnec->alloc(tinyInfo[7],1);
3112 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3113 setConnectivity(myConnec, myConnecIndex);
3118 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3119 * CellIds are given using range specified by a start an end and step.
3121 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3123 checkFullyDefined();
3124 int ncell=getNumberOfCells();
3125 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3126 ret->_mesh_dim=_mesh_dim;
3127 ret->setCoords(_coords);
3128 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3129 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3130 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3132 const int *conn=_nodal_connec->getConstPointer();
3133 const int *connIndex=_nodal_connec_index->getConstPointer();
3134 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3136 if(work>=0 && work<ncell)
3138 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3142 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3143 throw INTERP_KERNEL::Exception(oss.str().c_str());
3146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3147 int *newConnPtr=newConn->getPointer();
3148 std::set<INTERP_KERNEL::NormalizedCellType> types;
3150 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3152 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3153 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3155 ret->setConnectivity(newConn,newConnI,false);
3157 ret->copyTinyInfoFrom(this);
3162 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3163 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3164 * The return newly allocated mesh will share the same coordinates as \a this.
3166 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3168 checkConnectivityFullyDefined();
3169 int ncell=getNumberOfCells();
3170 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3171 ret->_mesh_dim=_mesh_dim;
3172 ret->setCoords(_coords);
3173 std::size_t nbOfElemsRet=std::distance(begin,end);
3174 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3176 const int *conn=_nodal_connec->getConstPointer();
3177 const int *connIndex=_nodal_connec_index->getConstPointer();
3179 for(const int *work=begin;work!=end;work++,newNbring++)
3181 if(*work>=0 && *work<ncell)
3182 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3186 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3187 throw INTERP_KERNEL::Exception(oss.str().c_str());
3190 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3191 int *connRetWork=connRet;
3192 std::set<INTERP_KERNEL::NormalizedCellType> types;
3193 for(const int *work=begin;work!=end;work++)
3195 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3196 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3199 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3201 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3202 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3204 ret->copyTinyInfoFrom(this);
3209 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3211 * For 1D cells, the returned field contains lengths.<br>
3212 * For 2D cells, the returned field contains areas.<br>
3213 * For 3D cells, the returned field contains volumes.
3214 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3215 * orientation, i.e. the volume is always positive.
3216 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3217 * and one time . The caller is to delete this field using decrRef() as it is no
3220 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3222 std::string name="MeasureOfMesh_";
3224 int nbelem=getNumberOfCells();
3225 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3226 field->setName(name.c_str());
3227 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3228 array->alloc(nbelem,1);
3229 double *area_vol=array->getPointer();
3230 field->setArray(array) ; array=0;
3231 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3232 field->synchronizeTimeWithMesh();
3233 if(getMeshDimension()!=-1)
3236 INTERP_KERNEL::NormalizedCellType type;
3237 int dim_space=getSpaceDimension();
3238 const double *coords=getCoords()->getConstPointer();
3239 const int *connec=getNodalConnectivity()->getConstPointer();
3240 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3241 for(int iel=0;iel<nbelem;iel++)
3243 ipt=connec_index[iel];
3244 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3245 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);
3248 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3252 area_vol[0]=std::numeric_limits<double>::max();
3254 return field.retn();
3258 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3260 * For 1D cells, the returned array contains lengths.<br>
3261 * For 2D cells, the returned array contains areas.<br>
3262 * For 3D cells, the returned array contains volumes.
3263 * This method avoids building explicitly a part of \a this mesh to perform the work.
3264 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3265 * orientation, i.e. the volume is always positive.
3266 * \param [in] begin - an array of cell ids of interest.
3267 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3268 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3269 * delete this array using decrRef() as it is no more needed.
3271 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3272 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3273 * \sa getMeasureField()
3275 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3277 std::string name="PartMeasureOfMesh_";
3279 int nbelem=(int)std::distance(begin,end);
3280 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3281 array->setName(name.c_str());
3282 array->alloc(nbelem,1);
3283 double *area_vol=array->getPointer();
3284 if(getMeshDimension()!=-1)
3287 INTERP_KERNEL::NormalizedCellType type;
3288 int dim_space=getSpaceDimension();
3289 const double *coords=getCoords()->getConstPointer();
3290 const int *connec=getNodalConnectivity()->getConstPointer();
3291 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3292 for(const int *iel=begin;iel!=end;iel++)
3294 ipt=connec_index[*iel];
3295 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3296 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3299 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3303 area_vol[0]=std::numeric_limits<double>::max();
3305 return array.retn();
3309 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3310 * \a this one. The returned field contains the dual cell volume for each corresponding
3311 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3312 * the dual mesh in P1 sens of \a this.<br>
3313 * For 1D cells, the returned field contains lengths.<br>
3314 * For 2D cells, the returned field contains areas.<br>
3315 * For 3D cells, the returned field contains volumes.
3316 * This method is useful to check "P1*" conservative interpolators.
3317 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3318 * orientation, i.e. the volume is always positive.
3319 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3320 * nodes and one time. The caller is to delete this array using decrRef() as
3321 * it is no more needed.
3323 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3325 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3326 std::string name="MeasureOnNodeOfMesh_";
3328 int nbNodes=getNumberOfNodes();
3329 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3330 double cst=1./((double)getMeshDimension()+1.);
3331 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3332 array->alloc(nbNodes,1);
3333 double *valsToFill=array->getPointer();
3334 std::fill(valsToFill,valsToFill+nbNodes,0.);
3335 const double *values=tmp->getArray()->getConstPointer();
3336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3338 getReverseNodalConnectivity(da,daInd);
3339 const int *daPtr=da->getConstPointer();
3340 const int *daIPtr=daInd->getConstPointer();
3341 for(int i=0;i<nbNodes;i++)
3342 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3343 valsToFill[i]+=cst*values[*cell];
3345 ret->setArray(array);
3350 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3351 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3352 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3353 * and are normalized.
3354 * <br> \a this can be either
3355 * - a 2D mesh in 2D or 3D space or
3356 * - an 1D mesh in 2D space.
3358 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3359 * cells and one time. The caller is to delete this field using decrRef() as
3360 * it is no more needed.
3361 * \throw If the nodal connectivity of cells is not defined.
3362 * \throw If the coordinates array is not set.
3363 * \throw If the mesh dimension is not set.
3364 * \throw If the mesh and space dimension is not as specified above.
3366 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3368 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3369 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3370 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3371 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3372 int nbOfCells=getNumberOfCells();
3373 int nbComp=getMeshDimension()+1;
3374 array->alloc(nbOfCells,nbComp);
3375 double *vals=array->getPointer();
3376 const int *connI=_nodal_connec_index->getConstPointer();
3377 const int *conn=_nodal_connec->getConstPointer();
3378 const double *coords=_coords->getConstPointer();
3379 if(getMeshDimension()==2)
3381 if(getSpaceDimension()==3)
3383 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3384 const double *locPtr=loc->getConstPointer();
3385 for(int i=0;i<nbOfCells;i++,vals+=3)
3387 int offset=connI[i];
3388 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3389 double n=INTERP_KERNEL::norm<3>(vals);
3390 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3395 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3396 const double *isAbsPtr=isAbs->getArray()->begin();
3397 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3398 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3401 else//meshdimension==1
3404 for(int i=0;i<nbOfCells;i++)
3406 int offset=connI[i];
3407 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3408 double n=INTERP_KERNEL::norm<2>(tmp);
3409 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3414 ret->setArray(array);
3416 ret->synchronizeTimeWithSupport();
3421 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3422 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3423 * and are normalized.
3424 * <br> \a this can be either
3425 * - a 2D mesh in 2D or 3D space or
3426 * - an 1D mesh in 2D space.
3428 * This method avoids building explicitly a part of \a this mesh to perform the work.
3429 * \param [in] begin - an array of cell ids of interest.
3430 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3431 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3432 * cells and one time. The caller is to delete this field using decrRef() as
3433 * it is no more needed.
3434 * \throw If the nodal connectivity of cells is not defined.
3435 * \throw If the coordinates array is not set.
3436 * \throw If the mesh dimension is not set.
3437 * \throw If the mesh and space dimension is not as specified above.
3438 * \sa buildOrthogonalField()
3440 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3441 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3443 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3445 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3446 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3447 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3448 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3449 std::size_t nbelems=std::distance(begin,end);
3450 int nbComp=getMeshDimension()+1;
3451 array->alloc((int)nbelems,nbComp);
3452 double *vals=array->getPointer();
3453 const int *connI=_nodal_connec_index->getConstPointer();
3454 const int *conn=_nodal_connec->getConstPointer();
3455 const double *coords=_coords->getConstPointer();
3456 if(getMeshDimension()==2)
3458 if(getSpaceDimension()==3)
3460 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3461 const double *locPtr=loc->getConstPointer();
3462 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3464 int offset=connI[*i];
3465 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3466 double n=INTERP_KERNEL::norm<3>(vals);
3467 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3472 for(std::size_t i=0;i<nbelems;i++)
3473 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3476 else//meshdimension==1
3479 for(const int *i=begin;i!=end;i++)
3481 int offset=connI[*i];
3482 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3483 double n=INTERP_KERNEL::norm<2>(tmp);
3484 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3489 ret->setArray(array);
3491 ret->synchronizeTimeWithSupport();
3496 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3497 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3498 * and are \b not normalized.
3499 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3500 * cells and one time. The caller is to delete this field using decrRef() as
3501 * it is no more needed.
3502 * \throw If the nodal connectivity of cells is not defined.
3503 * \throw If the coordinates array is not set.
3504 * \throw If \a this->getMeshDimension() != 1.
3505 * \throw If \a this mesh includes cells of type other than SEG2.
3507 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3509 if(getMeshDimension()!=1)
3510 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3511 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3512 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3513 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3514 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3515 int nbOfCells=getNumberOfCells();
3516 int spaceDim=getSpaceDimension();
3517 array->alloc(nbOfCells,spaceDim);
3518 double *pt=array->getPointer();
3519 const double *coo=getCoords()->getConstPointer();
3520 std::vector<int> conn;
3522 for(int i=0;i<nbOfCells;i++)
3525 getNodeIdsOfCell(i,conn);
3526 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3528 ret->setArray(array);
3530 ret->synchronizeTimeWithSupport();
3535 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3536 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3537 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3538 * from. If a result face is shared by two 3D cells, then the face in included twice in
3540 * \param [in] origin - 3 components of a point defining location of the plane.
3541 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3542 * must be greater than 1e-6.
3543 * \param [in] eps - half-thickness of the plane.
3544 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3545 * producing correspondent 2D cells. The caller is to delete this array
3546 * using decrRef() as it is no more needed.
3547 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3548 * not share the node coordinates array with \a this mesh. The caller is to
3549 * delete this mesh using decrRef() as it is no more needed.
3550 * \throw If the coordinates array is not set.
3551 * \throw If the nodal connectivity of cells is not defined.
3552 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3553 * \throw If magnitude of \a vec is less than 1e-6.
3554 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3555 * \throw If \a this includes quadratic cells.
3557 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3559 checkFullyDefined();
3560 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3561 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3563 if(candidates->empty())
3564 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3565 std::vector<int> nodes;
3566 DataArrayInt *cellIds1D=0;
3567 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3568 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3571 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3572 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3573 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3574 revDesc2=0; revDescIndx2=0;
3575 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3576 revDesc1=0; revDescIndx1=0;
3577 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3578 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3580 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3581 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3583 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3584 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3585 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3586 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3587 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3589 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3590 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3591 if(cellIds2->empty())
3592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3593 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3594 ret->setCoords(mDesc1->getCoords());
3595 ret->setConnectivity(conn,connI,true);
3596 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3601 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3602 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
3603 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3605 * \param [in] origin - 3 components of a point defining location of the plane.
3606 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3607 * must be greater than 1e-6.
3608 * \param [in] eps - half-thickness of the plane.
3609 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3610 * producing correspondent segments. The caller is to delete this array
3611 * using decrRef() as it is no more needed.
3612 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3613 * mesh in 3D space. This mesh does not share the node coordinates array with
3614 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3616 * \throw If the coordinates array is not set.
3617 * \throw If the nodal connectivity of cells is not defined.
3618 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3619 * \throw If magnitude of \a vec is less than 1e-6.
3620 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3621 * \throw If \a this includes quadratic cells.
3623 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3625 checkFullyDefined();
3626 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3629 if(candidates->empty())
3630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3631 std::vector<int> nodes;
3632 DataArrayInt *cellIds1D=0;
3633 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3634 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3635 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3639 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3640 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3643 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3644 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3646 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3647 int ncellsSub=subMesh->getNumberOfCells();
3648 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3649 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3650 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3651 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3654 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3655 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3656 for(int i=0;i<ncellsSub;i++)
3658 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3660 if(cut3DSurf[i].first!=-2)
3662 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3663 connI->pushBackSilent(conn->getNumberOfTuples());
3664 cellIds2->pushBackSilent(i);
3668 int cellId3DSurf=cut3DSurf[i].second;
3669 int offset=nodalI[cellId3DSurf]+1;
3670 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3671 for(int j=0;j<nbOfEdges;j++)
3673 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3674 connI->pushBackSilent(conn->getNumberOfTuples());
3675 cellIds2->pushBackSilent(cellId3DSurf);
3680 if(cellIds2->empty())
3681 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3682 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3683 ret->setCoords(mDesc1->getCoords());
3684 ret->setConnectivity(conn,connI,true);
3685 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3690 * Finds cells whose bounding boxes intersect a given plane.
3691 * \param [in] origin - 3 components of a point defining location of the plane.
3692 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3693 * must be greater than 1e-6.
3694 * \param [in] eps - half-thickness of the plane.
3695 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3696 * cells. The caller is to delete this array using decrRef() as it is no more
3698 * \throw If the coordinates array is not set.
3699 * \throw If the nodal connectivity of cells is not defined.
3700 * \throw If \a this->getSpaceDimension() != 3.
3701 * \throw If magnitude of \a vec is less than 1e-6.
3702 * \sa buildSlice3D()
3704 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3706 checkFullyDefined();
3707 if(getSpaceDimension()!=3)
3708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3709 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3711 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3713 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3714 double angle=acos(vec[2]/normm);
3715 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3719 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3720 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3721 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3723 mw->getBoundingBox(bbox);
3724 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3725 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3729 getBoundingBox(bbox);
3730 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3731 cellIds=getCellsInBoundingBox(bbox,eps);
3733 return cellIds.retn();
3737 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3738 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3739 * No consideration of coordinate is done by this method.
3740 * 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)
3741 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3743 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3745 if(getMeshDimension()!=1)
3746 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3747 int nbCells=getNumberOfCells();
3749 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3750 const int *connI=_nodal_connec_index->getConstPointer();
3751 const int *conn=_nodal_connec->getConstPointer();
3752 int ref=conn[connI[0]+2];
3753 for(int i=1;i<nbCells;i++)
3755 if(conn[connI[i]+1]!=ref)
3757 ref=conn[connI[i]+2];
3763 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3764 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3765 * \param pt reference point of the line
3766 * \param v normalized director vector of the line
3767 * \param eps max precision before throwing an exception
3768 * \param res output of size this->getNumberOfCells
3770 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3772 if(getMeshDimension()!=1)
3773 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3774 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3775 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3776 if(getSpaceDimension()!=3)
3777 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3778 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3779 const double *fPtr=f->getArray()->getConstPointer();
3781 for(int i=0;i<getNumberOfCells();i++)
3783 const double *tmp1=fPtr+3*i;
3784 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3785 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3786 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3787 double n1=INTERP_KERNEL::norm<3>(tmp);
3788 n1/=INTERP_KERNEL::norm<3>(tmp1);
3790 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3792 const double *coo=getCoords()->getConstPointer();
3793 for(int i=0;i<getNumberOfNodes();i++)
3795 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3796 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3797 res[i]=std::accumulate(tmp,tmp+3,0.);
3802 * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance.
3803 * \a this is expected to be a mesh so that its space dimension is equal to its
3804 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3805 * 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).
3807 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3808 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3809 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3811 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3812 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3814 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3815 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3816 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3817 * \return the positive value of the distance.
3818 * \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
3820 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3822 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3824 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3825 if(meshDim!=spaceDim-1)
3826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3827 if(meshDim!=2 && meshDim!=1)
3828 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3829 checkFullyDefined();
3830 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3831 { 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()); }
3832 DataArrayInt *ret1=0;
3833 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3834 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3836 cellId=*ret1Safe->begin();
3837 return *ret0->begin();
3841 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3842 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3843 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3844 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3845 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3847 * \a this is expected to be a mesh so that its space dimension is equal to its
3848 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3849 * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3851 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3852 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3854 * \param [in] pts the list of points in which each tuple represents a point
3855 * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
3856 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3857 * \throw if number of components of \a pts is not equal to the space dimension.
3858 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3859 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3861 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3865 pts->checkAllocated();
3866 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3867 if(meshDim!=spaceDim-1)
3868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3869 if(meshDim!=2 && meshDim!=1)
3870 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3871 if(pts->getNumberOfComponents()!=spaceDim)
3873 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3874 throw INTERP_KERNEL::Exception(oss.str().c_str());
3876 checkFullyDefined();
3877 int nbCells=getNumberOfCells();
3879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3880 int nbOfPts=pts->getNumberOfTuples();
3881 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3883 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3884 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3885 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3886 const double *bbox(bboxArr->begin());
3891 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3892 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3894 double x=std::numeric_limits<double>::max();
3895 std::vector<int> elems;
3896 myTree.getMinDistanceOfMax(ptsPtr,x);
3897 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3898 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3904 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3905 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3907 double x=std::numeric_limits<double>::max();
3908 std::vector<int> elems;
3909 myTree.getMinDistanceOfMax(ptsPtr,x);
3910 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3911 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3918 cellIds=ret1.retn();
3923 * \param [in] pt the start pointer (included) of the coordinates of the point
3924 * \param [in] cellIdsBg the start pointer (included) of cellIds
3925 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3926 * \param [in] nc nodal connectivity
3927 * \param [in] ncI nodal connectivity index
3928 * \param [in,out] ret0 the min distance between \a this and the external input point
3929 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3930 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3932 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3935 ret0=std::numeric_limits<double>::max();
3936 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3938 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3940 case INTERP_KERNEL::NORM_TRI3:
3942 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3944 { ret0=tmp; cellId=*zeCell; }
3947 case INTERP_KERNEL::NORM_QUAD4:
3948 case INTERP_KERNEL::NORM_POLYGON:
3950 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3952 { ret0=tmp; cellId=*zeCell; }
3956 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3962 * \param [in] pt the start pointer (included) of the coordinates of the point
3963 * \param [in] cellIdsBg the start pointer (included) of cellIds
3964 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3965 * \param [in] nc nodal connectivity
3966 * \param [in] ncI nodal connectivity index
3967 * \param [in,out] ret0 the min distance between \a this and the external input point
3968 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3969 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3971 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3974 ret0=std::numeric_limits<double>::max();
3975 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3977 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3979 case INTERP_KERNEL::NORM_SEG2:
3981 std::size_t uselessEntry=0;
3982 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3985 { ret0=tmp; cellId=*zeCell; }
3989 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3995 * Finds cells in contact with a ball (i.e. a point with precision).
3996 * \warning This method is suitable if the caller intends to evaluate only one
3997 * point, for more points getCellsContainingPoints() is recommended as it is
3999 * \param [in] pos - array of coordinates of the ball central point.
4000 * \param [in] eps - ball radius.
4001 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4002 * if there are no such cells.
4003 * \throw If the coordinates array is not set.
4004 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4006 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4008 std::vector<int> elts;
4009 getCellsContainingPoint(pos,eps,elts);
4012 return elts.front();
4016 * Finds cells in contact with a ball (i.e. a point with precision).
4017 * \warning This method is suitable if the caller intends to evaluate only one
4018 * point, for more points getCellsContainingPoints() is recommended as it is
4020 * \param [in] pos - array of coordinates of the ball central point.
4021 * \param [in] eps - ball radius.
4022 * \param [out] elts - vector returning ids of the found cells. It is cleared
4023 * before inserting ids.
4024 * \throw If the coordinates array is not set.
4025 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4027 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4028 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4030 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4032 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4033 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4034 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4039 namespace ParaMEDMEM
4041 template<const int SPACEDIMM>
4045 static const int MY_SPACEDIM=SPACEDIMM;
4046 static const int MY_MESHDIM=8;
4047 typedef int MyConnType;
4048 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4050 // useless, but for windows compilation ...
4051 const double* getCoordinatesPtr() const { return 0; }
4052 const int* getConnectivityPtr() const { return 0; }
4053 const int* getConnectivityIndexPtr() const { return 0; }
4054 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4058 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4060 INTERP_KERNEL::Edge *ret=0;
4063 case INTERP_KERNEL::NORM_SEG2:
4065 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4068 case INTERP_KERNEL::NORM_SEG3:
4070 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4071 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4072 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4073 bool colinearity=inters.areColinears();
4074 delete e1; delete e2;
4076 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4078 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4079 mapp2[bg[2]].second=false;
4083 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4089 * 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'.
4090 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4091 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4093 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4096 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.
4097 const double *coo=mDesc->getCoords()->getConstPointer();
4098 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4099 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4101 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4102 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4103 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4105 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4106 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4108 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4109 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4111 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4112 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4114 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4116 if((*it2).second.second)
4117 mapp[(*it2).second.first]=(*it2).first;
4118 ((*it2).second.first)->decrRef();
4123 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4127 int locId=nodeId-offset2;
4128 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4132 int locId=nodeId-offset1;
4133 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4135 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4138 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4139 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4140 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4142 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4144 int eltId1=abs(*desc1)-1;
4145 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4147 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4148 if(it==mappRev.end())
4150 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4161 template<int SPACEDIM>
4162 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4163 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4165 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4166 int *eltsIndexPtr(eltsIndex->getPointer());
4167 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4168 const double *bbox(bboxArr->begin());
4169 int nbOfCells=getNumberOfCells();
4170 const int *conn=_nodal_connec->getConstPointer();
4171 const int *connI=_nodal_connec_index->getConstPointer();
4172 double bb[2*SPACEDIM];
4173 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4174 for(int i=0;i<nbOfPoints;i++)
4176 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4177 for(int j=0;j<SPACEDIM;j++)
4179 bb[2*j]=pos[SPACEDIM*i+j];
4180 bb[2*j+1]=pos[SPACEDIM*i+j];
4182 std::vector<int> candidates;
4183 myTree.getIntersectingElems(bb,candidates);
4184 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4186 int sz=connI[(*iter)+1]-connI[*iter]-1;
4187 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4188 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4189 coords,conn+connI[*iter]+1,sz,eps))
4191 eltsIndexPtr[i+1]++;
4192 elts->pushBackSilent(*iter);
4198 * Finds cells in contact with several balls (i.e. points with precision).
4199 * This method is an extension of getCellContainingPoint() and
4200 * getCellsContainingPoint() for the case of multiple points.
4201 * \param [in] pos - an array of coordinates of points in full interlace mode :
4202 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4203 * this->getSpaceDimension() * \a nbOfPoints
4204 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4205 * \param [in] eps - radius of balls (i.e. the precision).
4206 * \param [out] elts - vector returning ids of found cells.
4207 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4208 * dividing cell ids in \a elts into groups each referring to one
4209 * point. Its every element (except the last one) is an index pointing to the
4210 * first id of a group of cells. For example cells in contact with the *i*-th
4211 * point are described by following range of indices:
4212 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4213 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4214 * Number of cells in contact with the *i*-th point is
4215 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4216 * \throw If the coordinates array is not set.
4217 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4219 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4220 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4222 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4223 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4225 int spaceDim=getSpaceDimension();
4226 int mDim=getMeshDimension();
4231 const double *coords=_coords->getConstPointer();
4232 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4239 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4241 else if(spaceDim==2)
4245 const double *coords=_coords->getConstPointer();
4246 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4249 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4251 else if(spaceDim==1)
4255 const double *coords=_coords->getConstPointer();
4256 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4259 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4262 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4266 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4267 * least two its edges intersect each other anywhere except their extremities. An
4268 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4269 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4270 * cleared before filling in.
4271 * \param [in] eps - precision.
4272 * \throw If \a this->getMeshDimension() != 2.
4273 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4275 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4277 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4278 if(getMeshDimension()!=2)
4279 throw INTERP_KERNEL::Exception(msg);
4280 int spaceDim=getSpaceDimension();
4281 if(spaceDim!=2 && spaceDim!=3)
4282 throw INTERP_KERNEL::Exception(msg);
4283 const int *conn=_nodal_connec->getConstPointer();
4284 const int *connI=_nodal_connec_index->getConstPointer();
4285 int nbOfCells=getNumberOfCells();
4286 std::vector<double> cell2DinS2;
4287 for(int i=0;i<nbOfCells;i++)
4289 int offset=connI[i];
4290 int nbOfNodesForCell=connI[i+1]-offset-1;
4291 if(nbOfNodesForCell<=3)
4293 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4294 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4295 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4302 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4304 * 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.
4305 * 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.
4307 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4308 * This convex envelop is computed using Jarvis march algorithm.
4309 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4310 * 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)
4311 * 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.
4313 * \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.
4315 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4317 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4318 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4319 checkFullyDefined();
4320 const double *coords=getCoords()->getConstPointer();
4321 int nbOfCells=getNumberOfCells();
4322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4323 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4324 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4325 int *workIndexOut=nodalConnecIndexOut->getPointer();
4327 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4328 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4329 std::set<INTERP_KERNEL::NormalizedCellType> types;
4330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4331 isChanged->alloc(0,1);
4332 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4334 int pos=nodalConnecOut->getNumberOfTuples();
4335 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4336 isChanged->pushBackSilent(i);
4337 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4338 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4340 if(isChanged->empty())
4342 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4344 return isChanged.retn();
4348 * This method is \b NOT const because it can modify \a this.
4349 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4350 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4351 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4352 * \b 1 for translation and rotation around point of 'mesh1D'.
4353 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4355 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4357 checkFullyDefined();
4358 mesh1D->checkFullyDefined();
4359 if(!mesh1D->isContiguous1D())
4360 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4361 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4362 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4363 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4364 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4365 if(mesh1D->getMeshDimension()!=1)
4366 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4368 if(isPresenceOfQuadratic())
4370 if(mesh1D->isFullyQuadratic())
4373 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4376 int oldNbOfNodes=getNumberOfNodes();
4377 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4382 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4387 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4391 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4393 setCoords(newCoords);
4394 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4400 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4401 * If it is not the case an exception will be thrown.
4402 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4403 * intersection of plane defined by ('origin','vec').
4404 * This method has one in/out parameter : 'cut3DCurve'.
4405 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4406 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4407 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4408 * This method will throw an exception if \a this contains a non linear segment.
4410 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4412 checkFullyDefined();
4413 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4415 int ncells=getNumberOfCells();
4416 int nnodes=getNumberOfNodes();
4417 double vec2[3],vec3[3],vec4[3];
4418 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4421 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4422 const int *conn=_nodal_connec->getConstPointer();
4423 const int *connI=_nodal_connec_index->getConstPointer();
4424 const double *coo=_coords->getConstPointer();
4425 std::vector<double> addCoo;
4426 for(int i=0;i<ncells;i++)
4428 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4430 if(cut3DCurve[i]==-2)
4432 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4433 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];
4434 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4435 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4436 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4438 const double *st2=coo+3*st;
4439 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4440 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]));
4441 if(pos>eps && pos<1-eps)
4443 int nNode=((int)addCoo.size())/3;
4444 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4445 addCoo.insert(addCoo.end(),vec4,vec4+3);
4446 cut3DCurve[i]=nnodes+nNode;
4452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4456 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4457 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4458 coo2->alloc(newNbOfNodes,3);
4459 double *tmp=coo2->getPointer();
4460 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4461 std::copy(addCoo.begin(),addCoo.end(),tmp);
4462 DataArrayDouble::SetArrayIn(coo2,_coords);
4467 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4468 * \param mesh1D is the input 1D mesh used for translation computation.
4469 * \return newCoords new coords filled by this method.
4471 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4473 int oldNbOfNodes=getNumberOfNodes();
4474 int nbOf1DCells=mesh1D->getNumberOfCells();
4475 int spaceDim=getSpaceDimension();
4476 DataArrayDouble *ret=DataArrayDouble::New();
4477 std::vector<bool> isQuads;
4478 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4479 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4480 double *retPtr=ret->getPointer();
4481 const double *coords=getCoords()->getConstPointer();
4482 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4484 std::vector<double> c;
4488 for(int i=0;i<nbOf1DCells;i++)
4491 mesh1D->getNodeIdsOfCell(i,v);
4493 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4494 mesh1D->getCoordinatesOfNode(v[0],c);
4495 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4496 for(int j=0;j<oldNbOfNodes;j++)
4497 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4501 mesh1D->getCoordinatesOfNode(v[1],c);
4502 mesh1D->getCoordinatesOfNode(v[0],c);
4503 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4504 for(int j=0;j<oldNbOfNodes;j++)
4505 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4508 ret->copyStringInfoFrom(*getCoords());
4513 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4514 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4515 * \return newCoords new coords filled by this method.
4517 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4519 if(mesh1D->getSpaceDimension()==2)
4520 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4521 if(mesh1D->getSpaceDimension()==3)
4522 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4523 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4527 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4528 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4529 * \return newCoords new coords filled by this method.
4531 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4534 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4535 int oldNbOfNodes=getNumberOfNodes();
4536 int nbOf1DCells=mesh1D->getNumberOfCells();
4538 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4539 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4540 int nbOfLevsInVec=nbOf1DCells+1;
4541 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4542 double *retPtr=ret->getPointer();
4543 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4544 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4545 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4546 tmp->setCoords(tmp2);
4547 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4548 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4549 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4550 for(int i=1;i<nbOfLevsInVec;i++)
4552 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4553 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4554 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4555 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4556 tmp->translate(vec);
4557 double tmp3[2],radius,alpha,alpha0;
4558 const double *p0=i+1<nbOfLevsInVec?begin:third;
4559 const double *p1=i+1<nbOfLevsInVec?end:begin;
4560 const double *p2=i+1<nbOfLevsInVec?third:end;
4561 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4562 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]);
4563 double angle=acos(cosangle/(radius*radius));
4564 tmp->rotate(end,0,angle);
4565 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4571 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4572 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4573 * \return newCoords new coords filled by this method.
4575 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4579 int oldNbOfNodes=getNumberOfNodes();
4580 int nbOf1DCells=mesh1D->getNumberOfCells();
4582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4583 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4584 int nbOfLevsInVec=nbOf1DCells+1;
4585 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4586 double *retPtr=ret->getPointer();
4587 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4588 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4589 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4590 tmp->setCoords(tmp2);
4591 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4592 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4593 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4594 for(int i=1;i<nbOfLevsInVec;i++)
4596 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4597 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4598 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4599 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4600 tmp->translate(vec);
4601 double tmp3[2],radius,alpha,alpha0;
4602 const double *p0=i+1<nbOfLevsInVec?begin:third;
4603 const double *p1=i+1<nbOfLevsInVec?end:begin;
4604 const double *p2=i+1<nbOfLevsInVec?third:end;
4605 double vecPlane[3]={
4606 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4607 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4608 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4610 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4613 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4614 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4615 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4617 double c2=cos(asin(s2));
4619 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4620 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4621 {-vec2[1]*s2, vec2[0]*s2, c2}
4623 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]};
4624 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]};
4625 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]};
4626 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4627 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]);
4628 double angle=acos(cosangle/(radius*radius));
4629 tmp->rotate(end,vecPlane,angle);
4632 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4638 * This method is private because not easy to use for end user. This method is const contrary to
4639 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4640 * the coords sorted slice by slice.
4641 * \param isQuad specifies presence of quadratic cells.
4643 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4645 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4646 int nbOf2DCells=getNumberOfCells();
4647 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4648 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4649 const int *conn=_nodal_connec->getConstPointer();
4650 const int *connI=_nodal_connec_index->getConstPointer();
4651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4653 newConnI->alloc(nbOf3DCells+1,1);
4654 int *newConnIPtr=newConnI->getPointer();
4656 std::vector<int> newc;
4657 for(int j=0;j<nbOf2DCells;j++)
4659 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4660 *newConnIPtr++=(int)newc.size();
4662 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4663 int *newConnPtr=newConn->getPointer();
4664 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4665 newConnIPtr=newConnI->getPointer();
4666 for(int iz=0;iz<nbOf1DCells;iz++)
4669 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4670 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4672 int icell=(int)(iter-newc.begin());
4673 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4676 *newConnPtr=(*iter)+iz*deltaPerLev;
4681 *newConnPtr=(*iter);
4684 ret->setConnectivity(newConn,newConnI,true);
4685 ret->setCoords(getCoords());
4690 * Checks if \a this mesh is constituted by only quadratic cells.
4691 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4692 * \throw If the coordinates array is not set.
4693 * \throw If the nodal connectivity of cells is not defined.
4695 bool MEDCouplingUMesh::isFullyQuadratic() const
4697 checkFullyDefined();
4699 int nbOfCells=getNumberOfCells();
4700 for(int i=0;i<nbOfCells && ret;i++)
4702 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4703 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4704 ret=cm.isQuadratic();
4710 * Checks if \a this mesh includes any quadratic cell.
4711 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4712 * \throw If the coordinates array is not set.
4713 * \throw If the nodal connectivity of cells is not defined.
4715 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4717 checkFullyDefined();
4719 int nbOfCells=getNumberOfCells();
4720 for(int i=0;i<nbOfCells && !ret;i++)
4722 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4723 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4724 ret=cm.isQuadratic();
4730 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4731 * this mesh, it remains unchanged.
4732 * \throw If the coordinates array is not set.
4733 * \throw If the nodal connectivity of cells is not defined.
4735 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4737 checkFullyDefined();
4738 int nbOfCells=getNumberOfCells();
4740 const int *iciptr=_nodal_connec_index->getConstPointer();
4741 for(int i=0;i<nbOfCells;i++)
4743 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4744 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4745 if(cm.isQuadratic())
4747 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4748 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4749 if(!cml.isDynamic())
4750 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4752 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4759 const int *icptr=_nodal_connec->getConstPointer();
4760 newConn->alloc(getMeshLength()-delta,1);
4761 newConnI->alloc(nbOfCells+1,1);
4762 int *ocptr=newConn->getPointer();
4763 int *ociptr=newConnI->getPointer();
4766 for(int i=0;i<nbOfCells;i++,ociptr++)
4768 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4769 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4770 if(!cm.isQuadratic())
4772 _types.insert(type);
4773 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4774 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4778 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4779 _types.insert(typel);
4780 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4781 int newNbOfNodes=cml.getNumberOfNodes();
4783 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4784 *ocptr++=(int)typel;
4785 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4786 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4789 setConnectivity(newConn,newConnI,false);
4793 * This method converts all linear cell in \a this to quadratic one.
4794 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4795 * 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)
4796 * 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.
4797 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4798 * end of the existing coordinates.
4800 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4801 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4802 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4804 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4806 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4808 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4810 DataArrayInt *conn=0,*connI=0;
4811 DataArrayDouble *coords=0;
4812 std::set<INTERP_KERNEL::NormalizedCellType> types;
4813 checkFullyDefined();
4814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4815 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4816 int meshDim=getMeshDimension();
4817 switch(conversionType)
4823 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4824 connSafe=conn; connISafe=connI; coordsSafe=coords;
4827 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4828 connSafe=conn; connISafe=connI; coordsSafe=coords;
4831 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4832 connSafe=conn; connISafe=connI; coordsSafe=coords;
4835 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4843 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4844 connSafe=conn; connISafe=connI; coordsSafe=coords;
4847 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4848 connSafe=conn; connISafe=connI; coordsSafe=coords;
4851 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4852 connSafe=conn; connISafe=connI; coordsSafe=coords;
4855 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4862 setConnectivity(connSafe,connISafe,false);
4864 setCoords(coordsSafe);
4869 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4870 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4871 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4873 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4875 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4879 int nbOfCells=getNumberOfCells();
4880 int nbOfNodes=getNumberOfNodes();
4881 const int *cPtr=_nodal_connec->getConstPointer();
4882 const int *icPtr=_nodal_connec_index->getConstPointer();
4883 int lastVal=0,offset=nbOfNodes;
4884 for(int i=0;i<nbOfCells;i++,icPtr++)
4886 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4887 if(type==INTERP_KERNEL::NORM_SEG2)
4889 types.insert(INTERP_KERNEL::NORM_SEG3);
4890 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4891 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4892 newConn->pushBackSilent(offset++);
4894 newConnI->pushBackSilent(lastVal);
4895 ret->pushBackSilent(i);
4900 lastVal+=(icPtr[1]-icPtr[0]);
4901 newConnI->pushBackSilent(lastVal);
4902 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4905 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4906 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4910 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)
4912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4916 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4917 DataArrayInt *conn1D=0,*conn1DI=0;
4918 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4919 DataArrayDouble *coordsTmp=0;
4920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4921 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4923 const int *c1DPtr=conn1D->begin();
4924 const int *c1DIPtr=conn1DI->begin();
4925 int nbOfCells=getNumberOfCells();
4926 const int *cPtr=_nodal_connec->getConstPointer();
4927 const int *icPtr=_nodal_connec_index->getConstPointer();
4929 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4931 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4932 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4933 if(!cm.isQuadratic())
4935 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4936 types.insert(typ2); newConn->pushBackSilent(typ2);
4937 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4938 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4939 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4940 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4941 newConnI->pushBackSilent(lastVal);
4942 ret->pushBackSilent(i);
4947 lastVal+=(icPtr[1]-icPtr[0]);
4948 newConnI->pushBackSilent(lastVal);
4949 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4952 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4957 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4958 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4959 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4961 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4965 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4966 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4969 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4971 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4972 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4978 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4979 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4980 DataArrayInt *conn1D=0,*conn1DI=0;
4981 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4982 DataArrayDouble *coordsTmp=0;
4983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4984 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4985 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4986 const int *c1DPtr=conn1D->begin();
4987 const int *c1DIPtr=conn1DI->begin();
4988 int nbOfCells=getNumberOfCells();
4989 const int *cPtr=_nodal_connec->getConstPointer();
4990 const int *icPtr=_nodal_connec_index->getConstPointer();
4991 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4992 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4994 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4995 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4996 if(!cm.isQuadratic())
4998 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4999 types.insert(typ2); newConn->pushBackSilent(typ2);
5000 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5001 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5002 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5003 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5004 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5005 newConnI->pushBackSilent(lastVal);
5006 ret->pushBackSilent(i);
5011 lastVal+=(icPtr[1]-icPtr[0]);
5012 newConnI->pushBackSilent(lastVal);
5013 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5016 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5017 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5022 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5023 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5024 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5026 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5029 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5030 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5033 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5036 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5037 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5038 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5041 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5042 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5044 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5045 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5046 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5047 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5048 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5051 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5053 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5055 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5056 int nbOfCells=getNumberOfCells();
5057 const int *cPtr=_nodal_connec->getConstPointer();
5058 const int *icPtr=_nodal_connec_index->getConstPointer();
5059 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5060 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5062 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5063 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5064 if(!cm.isQuadratic())
5066 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5067 if(typ2==INTERP_KERNEL::NORM_ERROR)
5069 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5070 throw INTERP_KERNEL::Exception(oss.str().c_str());
5072 types.insert(typ2); newConn->pushBackSilent(typ2);
5073 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5074 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5075 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5076 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5078 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5079 int tmpPos=newConn->getNumberOfTuples();
5080 newConn->pushBackSilent(nodeId2);
5081 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5083 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5084 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5085 newConnI->pushBackSilent(lastVal);
5086 ret->pushBackSilent(i);
5091 lastVal+=(icPtr[1]-icPtr[0]);
5092 newConnI->pushBackSilent(lastVal);
5093 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5098 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5099 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5100 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5101 int *c=newConn->getPointer();
5102 const int *cI(newConnI->begin());
5103 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5104 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5105 offset=coordsTmp2Safe->getNumberOfTuples();
5106 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5107 c[cI[(*elt)+1]-1]+=offset;
5108 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5113 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5114 * so that the number of cells remains the same. Quadratic faces are converted to
5115 * polygons. This method works only for 2D meshes in
5116 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5117 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5118 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5119 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5120 * a polylinized edge constituting the input polygon.
5121 * \throw If the coordinates array is not set.
5122 * \throw If the nodal connectivity of cells is not defined.
5123 * \throw If \a this->getMeshDimension() != 2.
5124 * \throw If \a this->getSpaceDimension() != 2.
5126 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5128 checkFullyDefined();
5129 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5130 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5131 double epsa=fabs(eps);
5132 if(epsa<std::numeric_limits<double>::min())
5133 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 !");
5134 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5137 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5138 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5139 revDesc1=0; revDescIndx1=0;
5140 mDesc->tessellate2DCurve(eps);
5141 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5142 setCoords(mDesc->getCoords());
5146 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5147 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5148 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5149 * a sub-divided edge.
5150 * \throw If the coordinates array is not set.
5151 * \throw If the nodal connectivity of cells is not defined.
5152 * \throw If \a this->getMeshDimension() != 1.
5153 * \throw If \a this->getSpaceDimension() != 2.
5155 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5157 checkFullyDefined();
5158 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5159 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5160 double epsa=fabs(eps);
5161 if(epsa<std::numeric_limits<double>::min())
5162 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 !");
5163 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5164 int nbCells=getNumberOfCells();
5165 int nbNodes=getNumberOfNodes();
5166 const int *conn=_nodal_connec->getConstPointer();
5167 const int *connI=_nodal_connec_index->getConstPointer();
5168 const double *coords=_coords->getConstPointer();
5169 std::vector<double> addCoo;
5170 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5172 newConnI->alloc(nbCells+1,1);
5173 int *newConnIPtr=newConnI->getPointer();
5176 INTERP_KERNEL::Node *tmp2[3];
5177 std::set<INTERP_KERNEL::NormalizedCellType> types;
5178 for(int i=0;i<nbCells;i++,newConnIPtr++)
5180 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5181 if(cm.isQuadratic())
5182 {//assert(connI[i+1]-connI[i]-1==3)
5183 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5184 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5185 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5186 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5187 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5190 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5191 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5193 newConnIPtr[1]=(int)newConn.size();
5197 types.insert(INTERP_KERNEL::NORM_SEG2);
5198 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5199 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5200 newConnIPtr[1]=newConnIPtr[0]+3;
5205 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5206 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5207 newConnIPtr[1]=newConnIPtr[0]+3;
5210 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5213 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5215 newConnArr->alloc((int)newConn.size(),1);
5216 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5217 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5218 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5219 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5220 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5221 std::copy(addCoo.begin(),addCoo.end(),work);
5222 DataArrayDouble::SetArrayIn(newCoords,_coords);
5227 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5228 * In addition, returns an array mapping new cells to old ones. <br>
5229 * This method typically increases the number of cells in \a this mesh
5230 * but the number of nodes remains \b unchanged.
5231 * That's why the 3D splitting policies
5232 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5233 * \param [in] policy - specifies a pattern used for splitting.
5234 * The semantic of \a policy is:
5235 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5236 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5237 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5238 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5239 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5240 * an id of old cell producing it. The caller is to delete this array using
5241 * decrRef() as it is no more needed.
5242 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5243 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5244 * and \a this->getMeshDimension() != 3.
5245 * \throw If \a policy is not one of the four discussed above.
5246 * \throw If the nodal connectivity of cells is not defined.
5247 * \sa MEDCouplingUMesh::tetrahedrize
5249 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5254 return simplexizePol0();
5256 return simplexizePol1();
5257 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5258 return simplexizePlanarFace5();
5259 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5260 return simplexizePlanarFace6();
5262 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)");
5267 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5268 * - 1D: INTERP_KERNEL::NORM_SEG2
5269 * - 2D: INTERP_KERNEL::NORM_TRI3
5270 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5272 * This method is useful for users that need to use P1 field services as
5273 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5274 * All these methods need mesh support containing only simplex cells.
5275 * \return bool - \c true if there are only simplex cells in \a this mesh.
5276 * \throw If the coordinates array is not set.
5277 * \throw If the nodal connectivity of cells is not defined.
5278 * \throw If \a this->getMeshDimension() < 1.
5280 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5282 checkFullyDefined();
5283 int mdim=getMeshDimension();
5284 if(mdim<1 || mdim>3)
5285 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5286 int nbCells=getNumberOfCells();
5287 const int *conn=_nodal_connec->getConstPointer();
5288 const int *connI=_nodal_connec_index->getConstPointer();
5289 for(int i=0;i<nbCells;i++)
5291 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5299 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5301 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5303 checkConnectivityFullyDefined();
5304 if(getMeshDimension()!=2)
5305 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5306 int nbOfCells=getNumberOfCells();
5307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5308 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5309 ret->alloc(nbOfCells+nbOfCutCells,1);
5310 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5311 int *retPt=ret->getPointer();
5312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5313 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5314 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5315 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5316 int *pt=newConn->getPointer();
5317 int *ptI=newConnI->getPointer();
5319 const int *oldc=_nodal_connec->getConstPointer();
5320 const int *ci=_nodal_connec_index->getConstPointer();
5321 for(int i=0;i<nbOfCells;i++,ci++)
5323 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5325 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5326 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5327 pt=std::copy(tmp,tmp+8,pt);
5336 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5337 ptI[1]=ptI[0]+ci[1]-ci[0];
5342 _nodal_connec->decrRef();
5343 _nodal_connec=newConn.retn();
5344 _nodal_connec_index->decrRef();
5345 _nodal_connec_index=newConnI.retn();
5352 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5354 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5356 checkConnectivityFullyDefined();
5357 if(getMeshDimension()!=2)
5358 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5359 int nbOfCells=getNumberOfCells();
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5361 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5362 ret->alloc(nbOfCells+nbOfCutCells,1);
5363 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5364 int *retPt=ret->getPointer();
5365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5367 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5368 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5369 int *pt=newConn->getPointer();
5370 int *ptI=newConnI->getPointer();
5372 const int *oldc=_nodal_connec->getConstPointer();
5373 const int *ci=_nodal_connec_index->getConstPointer();
5374 for(int i=0;i<nbOfCells;i++,ci++)
5376 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5378 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5379 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5380 pt=std::copy(tmp,tmp+8,pt);
5389 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5390 ptI[1]=ptI[0]+ci[1]-ci[0];
5395 _nodal_connec->decrRef();
5396 _nodal_connec=newConn.retn();
5397 _nodal_connec_index->decrRef();
5398 _nodal_connec_index=newConnI.retn();
5405 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5407 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5409 checkConnectivityFullyDefined();
5410 if(getMeshDimension()!=3)
5411 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5412 int nbOfCells=getNumberOfCells();
5413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5414 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5415 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5416 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5417 int *retPt=ret->getPointer();
5418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5420 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5421 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5422 int *pt=newConn->getPointer();
5423 int *ptI=newConnI->getPointer();
5425 const int *oldc=_nodal_connec->getConstPointer();
5426 const int *ci=_nodal_connec_index->getConstPointer();
5427 for(int i=0;i<nbOfCells;i++,ci++)
5429 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5431 for(int j=0;j<5;j++,pt+=5,ptI++)
5433 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5434 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];
5441 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5442 ptI[1]=ptI[0]+ci[1]-ci[0];
5447 _nodal_connec->decrRef();
5448 _nodal_connec=newConn.retn();
5449 _nodal_connec_index->decrRef();
5450 _nodal_connec_index=newConnI.retn();
5457 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5459 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5461 checkConnectivityFullyDefined();
5462 if(getMeshDimension()!=3)
5463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5464 int nbOfCells=getNumberOfCells();
5465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5466 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5467 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5468 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5469 int *retPt=ret->getPointer();
5470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5472 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5473 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5474 int *pt=newConn->getPointer();
5475 int *ptI=newConnI->getPointer();
5477 const int *oldc=_nodal_connec->getConstPointer();
5478 const int *ci=_nodal_connec_index->getConstPointer();
5479 for(int i=0;i<nbOfCells;i++,ci++)
5481 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5483 for(int j=0;j<6;j++,pt+=5,ptI++)
5485 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5486 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];
5493 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5494 ptI[1]=ptI[0]+ci[1]-ci[0];
5499 _nodal_connec->decrRef();
5500 _nodal_connec=newConn.retn();
5501 _nodal_connec_index->decrRef();
5502 _nodal_connec_index=newConnI.retn();
5509 * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5510 * This method completly ignore coordinates.
5511 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5512 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5513 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5514 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5516 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5518 checkFullyDefined();
5519 if(getMeshDimension()!=2)
5520 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5521 int nbOfCells=getNumberOfCells();
5522 int *connI=_nodal_connec_index->getPointer();
5524 for(int i=0;i<nbOfCells;i++,connI++)
5526 int offset=descIndex[i];
5527 int nbOfEdges=descIndex[i+1]-offset;
5529 bool ddirect=desc[offset+nbOfEdges-1]>0;
5530 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5531 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5532 for(int j=0;j<nbOfEdges;j++)
5534 bool direct=desc[offset+j]>0;
5535 int edgeId=std::abs(desc[offset+j])-1;
5536 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5538 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5539 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5540 int ref2=direct?id1:id2;
5543 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5544 newConnLgth+=nbOfSubNodes-1;
5549 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5550 throw INTERP_KERNEL::Exception(oss.str().c_str());
5555 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5558 newConnLgth++;//+1 is for cell type
5559 connI[1]=newConnLgth;
5562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5563 newConn->alloc(newConnLgth,1);
5564 int *work=newConn->getPointer();
5565 for(int i=0;i<nbOfCells;i++)
5567 *work++=INTERP_KERNEL::NORM_POLYGON;
5568 int offset=descIndex[i];
5569 int nbOfEdges=descIndex[i+1]-offset;
5570 for(int j=0;j<nbOfEdges;j++)
5572 bool direct=desc[offset+j]>0;
5573 int edgeId=std::abs(desc[offset+j])-1;
5575 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5578 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5579 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5580 work=std::copy(it,it+nbOfSubNodes-1,work);
5584 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5587 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5591 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5592 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5593 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5594 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5595 * so it can be useful to call mergeNodes() before calling this method.
5596 * \throw If \a this->getMeshDimension() <= 1.
5597 * \throw If the coordinates array is not set.
5598 * \throw If the nodal connectivity of cells is not defined.
5600 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5602 checkFullyDefined();
5603 if(getMeshDimension()<=1)
5604 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5605 int nbOfCells=getNumberOfCells();
5608 int initMeshLgth=getMeshLength();
5609 int *conn=_nodal_connec->getPointer();
5610 int *index=_nodal_connec_index->getPointer();
5614 for(int i=0;i<nbOfCells;i++)
5616 lgthOfCurCell=index[i+1]-posOfCurCell;
5617 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5619 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5620 conn+newPos+1,newLgth);
5621 conn[newPos]=newType;
5623 posOfCurCell=index[i+1];
5626 if(newPos!=initMeshLgth)
5627 _nodal_connec->reAlloc(newPos);
5632 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5633 * A cell is considered to be oriented correctly if an angle between its
5634 * normal vector and a given vector is less than \c PI / \c 2.
5635 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5637 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5639 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5640 * is not cleared before filling in.
5641 * \throw If \a this->getMeshDimension() != 2.
5642 * \throw If \a this->getSpaceDimension() != 3.
5644 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5645 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5647 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5649 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5650 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5651 int nbOfCells=getNumberOfCells();
5652 const int *conn=_nodal_connec->getConstPointer();
5653 const int *connI=_nodal_connec_index->getConstPointer();
5654 const double *coordsPtr=_coords->getConstPointer();
5655 for(int i=0;i<nbOfCells;i++)
5657 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5658 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5660 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5661 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5668 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5669 * considered to be oriented correctly if an angle between its normal vector and a
5670 * given vector is less than \c PI / \c 2.
5671 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5673 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5675 * \throw If \a this->getMeshDimension() != 2.
5676 * \throw If \a this->getSpaceDimension() != 3.
5678 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5679 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5681 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5683 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5684 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5685 int nbOfCells=getNumberOfCells();
5686 int *conn=_nodal_connec->getPointer();
5687 const int *connI=_nodal_connec_index->getConstPointer();
5688 const double *coordsPtr=_coords->getConstPointer();
5689 bool isModified=false;
5690 for(int i=0;i<nbOfCells;i++)
5692 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5693 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5695 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5696 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5699 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5700 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5701 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5706 _nodal_connec->declareAsNew();
5711 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5712 * oriented facets. The normal vector of the facet should point out of the cell.
5713 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5714 * is not cleared before filling in.
5715 * \throw If \a this->getMeshDimension() != 3.
5716 * \throw If \a this->getSpaceDimension() != 3.
5717 * \throw If the coordinates array is not set.
5718 * \throw If the nodal connectivity of cells is not defined.
5720 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5721 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5723 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5725 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5726 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5727 int nbOfCells=getNumberOfCells();
5728 const int *conn=_nodal_connec->getConstPointer();
5729 const int *connI=_nodal_connec_index->getConstPointer();
5730 const double *coordsPtr=_coords->getConstPointer();
5731 for(int i=0;i<nbOfCells;i++)
5733 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5734 if(type==INTERP_KERNEL::NORM_POLYHED)
5736 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5743 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5745 * \throw If \a this->getMeshDimension() != 3.
5746 * \throw If \a this->getSpaceDimension() != 3.
5747 * \throw If the coordinates array is not set.
5748 * \throw If the nodal connectivity of cells is not defined.
5749 * \throw If the reparation fails.
5751 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5752 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5753 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5755 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5757 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5758 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5759 int nbOfCells=getNumberOfCells();
5760 int *conn=_nodal_connec->getPointer();
5761 const int *connI=_nodal_connec_index->getConstPointer();
5762 const double *coordsPtr=_coords->getConstPointer();
5763 for(int i=0;i<nbOfCells;i++)
5765 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5766 if(type==INTERP_KERNEL::NORM_POLYHED)
5770 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5771 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5773 catch(INTERP_KERNEL::Exception& e)
5775 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5776 throw INTERP_KERNEL::Exception(oss.str().c_str());
5784 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5785 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5786 * according to which the first facet of the cell should be oriented to have the normal vector
5787 * pointing out of cell.
5788 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5789 * cells. The caller is to delete this array using decrRef() as it is no more
5791 * \throw If \a this->getMeshDimension() != 3.
5792 * \throw If \a this->getSpaceDimension() != 3.
5793 * \throw If the coordinates array is not set.
5794 * \throw If the nodal connectivity of cells is not defined.
5796 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5797 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5798 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5800 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5802 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5803 if(getMeshDimension()!=3)
5804 throw INTERP_KERNEL::Exception(msg);
5805 int spaceDim=getSpaceDimension();
5807 throw INTERP_KERNEL::Exception(msg);
5809 int nbOfCells=getNumberOfCells();
5810 int *conn=_nodal_connec->getPointer();
5811 const int *connI=_nodal_connec_index->getConstPointer();
5812 const double *coo=getCoords()->getConstPointer();
5813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5814 for(int i=0;i<nbOfCells;i++)
5816 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5817 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5819 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5821 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5822 cells->pushBackSilent(i);
5826 return cells.retn();
5830 * This method is a faster method to correct orientation of all 3D cells in \a this.
5831 * 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.
5832 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5834 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5835 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5837 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5839 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5840 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5841 int nbOfCells=getNumberOfCells();
5842 int *conn=_nodal_connec->getPointer();
5843 const int *connI=_nodal_connec_index->getConstPointer();
5844 const double *coordsPtr=_coords->getConstPointer();
5845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5846 for(int i=0;i<nbOfCells;i++)
5848 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5851 case INTERP_KERNEL::NORM_TETRA4:
5853 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5855 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5856 ret->pushBackSilent(i);
5860 case INTERP_KERNEL::NORM_PYRA5:
5862 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5864 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5865 ret->pushBackSilent(i);
5869 case INTERP_KERNEL::NORM_PENTA6:
5870 case INTERP_KERNEL::NORM_HEXA8:
5871 case INTERP_KERNEL::NORM_HEXGP12:
5873 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5875 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5876 ret->pushBackSilent(i);
5880 case INTERP_KERNEL::NORM_POLYHED:
5882 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5884 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5885 ret->pushBackSilent(i);
5890 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 !");
5898 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5899 * If it is not the case an exception will be thrown.
5900 * This method is fast because the first cell of \a this is used to compute the plane.
5901 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5902 * \param pos output of size at least 3 used to store a point owned of searched plane.
5904 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5906 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5907 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5908 const int *conn=_nodal_connec->getConstPointer();
5909 const int *connI=_nodal_connec_index->getConstPointer();
5910 const double *coordsPtr=_coords->getConstPointer();
5911 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5912 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5916 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5917 * cells. Currently cells of the following types are treated:
5918 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5919 * For a cell of other type an exception is thrown.
5920 * Space dimension of a 2D mesh can be either 2 or 3.
5921 * The Edge Ratio of a cell \f$t\f$ is:
5922 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5923 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5924 * the smallest edge lengths of \f$t\f$.
5925 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5926 * cells and one time, lying on \a this mesh. The caller is to delete this
5927 * field using decrRef() as it is no more needed.
5928 * \throw If the coordinates array is not set.
5929 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5930 * \throw If the connectivity data array has more than one component.
5931 * \throw If the connectivity data array has a named component.
5932 * \throw If the connectivity index data array has more than one component.
5933 * \throw If the connectivity index data array has a named component.
5934 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5935 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5936 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5938 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5941 int spaceDim=getSpaceDimension();
5942 int meshDim=getMeshDimension();
5943 if(spaceDim!=2 && spaceDim!=3)
5944 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5945 if(meshDim!=2 && meshDim!=3)
5946 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5947 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5949 int nbOfCells=getNumberOfCells();
5950 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5951 arr->alloc(nbOfCells,1);
5952 double *pt=arr->getPointer();
5953 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5954 const int *conn=_nodal_connec->getConstPointer();
5955 const int *connI=_nodal_connec_index->getConstPointer();
5956 const double *coo=_coords->getConstPointer();
5958 for(int i=0;i<nbOfCells;i++,pt++)
5960 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5963 case INTERP_KERNEL::NORM_TRI3:
5965 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5966 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5969 case INTERP_KERNEL::NORM_QUAD4:
5971 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5972 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5975 case INTERP_KERNEL::NORM_TETRA4:
5977 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5978 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5982 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5984 conn+=connI[i+1]-connI[i];
5986 ret->setName("EdgeRatio");
5987 ret->synchronizeTimeWithSupport();
5992 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5993 * cells. Currently cells of the following types are treated:
5994 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5995 * For a cell of other type an exception is thrown.
5996 * Space dimension of a 2D mesh can be either 2 or 3.
5997 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5998 * cells and one time, lying on \a this mesh. The caller is to delete this
5999 * field using decrRef() as it is no more needed.
6000 * \throw If the coordinates array is not set.
6001 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6002 * \throw If the connectivity data array has more than one component.
6003 * \throw If the connectivity data array has a named component.
6004 * \throw If the connectivity index data array has more than one component.
6005 * \throw If the connectivity index data array has a named component.
6006 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6007 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6008 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6010 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6013 int spaceDim=getSpaceDimension();
6014 int meshDim=getMeshDimension();
6015 if(spaceDim!=2 && spaceDim!=3)
6016 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6017 if(meshDim!=2 && meshDim!=3)
6018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6019 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6021 int nbOfCells=getNumberOfCells();
6022 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6023 arr->alloc(nbOfCells,1);
6024 double *pt=arr->getPointer();
6025 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6026 const int *conn=_nodal_connec->getConstPointer();
6027 const int *connI=_nodal_connec_index->getConstPointer();
6028 const double *coo=_coords->getConstPointer();
6030 for(int i=0;i<nbOfCells;i++,pt++)
6032 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6035 case INTERP_KERNEL::NORM_TRI3:
6037 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6038 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6041 case INTERP_KERNEL::NORM_QUAD4:
6043 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6044 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6047 case INTERP_KERNEL::NORM_TETRA4:
6049 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6050 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6054 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6056 conn+=connI[i+1]-connI[i];
6058 ret->setName("AspectRatio");
6059 ret->synchronizeTimeWithSupport();
6064 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6065 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6066 * treated: INTERP_KERNEL::NORM_QUAD4.
6067 * For a cell of other type an exception is thrown.
6068 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6069 * cells and one time, lying on \a this mesh. The caller is to delete this
6070 * field using decrRef() as it is no more needed.
6071 * \throw If the coordinates array is not set.
6072 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6073 * \throw If the connectivity data array has more than one component.
6074 * \throw If the connectivity data array has a named component.
6075 * \throw If the connectivity index data array has more than one component.
6076 * \throw If the connectivity index data array has a named component.
6077 * \throw If \a this->getMeshDimension() != 2.
6078 * \throw If \a this->getSpaceDimension() != 3.
6079 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6081 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6084 int spaceDim=getSpaceDimension();
6085 int meshDim=getMeshDimension();
6087 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6089 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6090 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6092 int nbOfCells=getNumberOfCells();
6093 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6094 arr->alloc(nbOfCells,1);
6095 double *pt=arr->getPointer();
6096 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6097 const int *conn=_nodal_connec->getConstPointer();
6098 const int *connI=_nodal_connec_index->getConstPointer();
6099 const double *coo=_coords->getConstPointer();
6101 for(int i=0;i<nbOfCells;i++,pt++)
6103 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6106 case INTERP_KERNEL::NORM_QUAD4:
6108 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6109 *pt=INTERP_KERNEL::quadWarp(tmp);
6113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6115 conn+=connI[i+1]-connI[i];
6117 ret->setName("Warp");
6118 ret->synchronizeTimeWithSupport();
6124 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6125 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6126 * treated: INTERP_KERNEL::NORM_QUAD4.
6127 * For a cell of other type an exception is thrown.
6128 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6129 * cells and one time, lying on \a this mesh. The caller is to delete this
6130 * field using decrRef() as it is no more needed.
6131 * \throw If the coordinates array is not set.
6132 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6133 * \throw If the connectivity data array has more than one component.
6134 * \throw If the connectivity data array has a named component.
6135 * \throw If the connectivity index data array has more than one component.
6136 * \throw If the connectivity index data array has a named component.
6137 * \throw If \a this->getMeshDimension() != 2.
6138 * \throw If \a this->getSpaceDimension() != 3.
6139 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6141 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6144 int spaceDim=getSpaceDimension();
6145 int meshDim=getMeshDimension();
6147 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6149 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6150 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6152 int nbOfCells=getNumberOfCells();
6153 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6154 arr->alloc(nbOfCells,1);
6155 double *pt=arr->getPointer();
6156 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6157 const int *conn=_nodal_connec->getConstPointer();
6158 const int *connI=_nodal_connec_index->getConstPointer();
6159 const double *coo=_coords->getConstPointer();
6161 for(int i=0;i<nbOfCells;i++,pt++)
6163 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6166 case INTERP_KERNEL::NORM_QUAD4:
6168 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6169 *pt=INTERP_KERNEL::quadSkew(tmp);
6173 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6175 conn+=connI[i+1]-connI[i];
6177 ret->setName("Skew");
6178 ret->synchronizeTimeWithSupport();
6183 * This method aggregate the bbox of each cell and put it into bbox parameter.
6185 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6187 * \throw If \a this is not fully set (coordinates and connectivity).
6188 * \throw If a cell in \a this has no valid nodeId.
6190 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6192 checkFullyDefined();
6193 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6194 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6195 double *bbox(ret->getPointer());
6196 for(int i=0;i<nbOfCells*spaceDim;i++)
6198 bbox[2*i]=std::numeric_limits<double>::max();
6199 bbox[2*i+1]=-std::numeric_limits<double>::max();
6201 const double *coordsPtr(_coords->getConstPointer());
6202 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6203 for(int i=0;i<nbOfCells;i++)
6205 int offset=connI[i]+1;
6206 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6207 for(int j=0;j<nbOfNodesForCell;j++)
6209 int nodeId=conn[offset+j];
6210 if(nodeId>=0 && nodeId<nbOfNodes)
6212 for(int k=0;k<spaceDim;k++)
6214 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6215 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6222 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6223 throw INTERP_KERNEL::Exception(oss.str().c_str());
6231 namespace ParaMEDMEMImpl
6236 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6237 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6246 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6247 bool operator() (const int& pos) { return _conn[pos]==_val; }
6257 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6258 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6259 * \a this is composed in cell types.
6260 * The returned array is of size 3*n where n is the number of different types present in \a this.
6261 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6262 * This parameter is kept only for compatibility with other methode listed above.
6264 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6266 checkConnectivityFullyDefined();
6267 const int *conn=_nodal_connec->getConstPointer();
6268 const int *connI=_nodal_connec_index->getConstPointer();
6269 const int *work=connI;
6270 int nbOfCells=getNumberOfCells();
6271 std::size_t n=getAllTypes().size();
6272 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6273 std::set<INTERP_KERNEL::NormalizedCellType> types;
6274 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6276 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6277 if(types.find(typ)!=types.end())
6279 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6280 oss << " is not contiguous !";
6281 throw INTERP_KERNEL::Exception(oss.str().c_str());
6285 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6286 ret[3*i+1]=(int)std::distance(work,work2);
6293 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6294 * only for types cell, type node is not managed.
6295 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6296 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6297 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6298 * If 2 or more same geometric type is in \a code and exception is thrown too.
6300 * This method firstly checks
6301 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6302 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6303 * an exception is thrown too.
6305 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6306 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6307 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6309 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6313 std::size_t sz=code.size();
6316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6317 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6319 bool isNoPflUsed=true;
6320 for(std::size_t i=0;i<n;i++)
6321 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6323 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6325 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6326 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6327 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6330 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6333 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6334 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6335 if(types.size()==_types.size())
6338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6340 int *retPtr=ret->getPointer();
6341 const int *connI=_nodal_connec_index->getConstPointer();
6342 const int *conn=_nodal_connec->getConstPointer();
6343 int nbOfCells=getNumberOfCells();
6346 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6348 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6349 int offset=(int)std::distance(connI,i);
6350 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6351 int nbOfCellsOfCurType=(int)std::distance(i,j);
6352 if(code[3*kk+2]==-1)
6353 for(int k=0;k<nbOfCellsOfCurType;k++)
6357 int idInIdsPerType=code[3*kk+2];
6358 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6360 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6363 zePfl->checkAllocated();
6364 if(zePfl->getNumberOfComponents()==1)
6366 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6368 if(*k>=0 && *k<nbOfCellsOfCurType)
6369 *retPtr=(*k)+offset;
6372 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6373 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6374 throw INTERP_KERNEL::Exception(oss.str().c_str());
6379 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6382 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6386 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6387 oss << " should be in [0," << idsPerType.size() << ") !";
6388 throw INTERP_KERNEL::Exception(oss.str().c_str());
6397 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6398 * 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.
6399 * 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.
6400 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6402 * \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.
6403 * \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,
6404 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6405 * \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.
6406 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6407 * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
6409 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6412 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6413 if(profile->getNumberOfComponents()!=1)
6414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6415 checkConnectivityFullyDefined();
6416 const int *conn=_nodal_connec->getConstPointer();
6417 const int *connI=_nodal_connec_index->getConstPointer();
6418 int nbOfCells=getNumberOfCells();
6419 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6420 std::vector<int> typeRangeVals(1);
6421 for(const int *i=connI;i!=connI+nbOfCells;)
6423 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6424 if(std::find(types.begin(),types.end(),curType)!=types.end())
6426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6428 types.push_back(curType);
6429 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6430 typeRangeVals.push_back((int)std::distance(connI,i));
6433 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6434 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6436 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6439 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6440 code.resize(3*nbOfCastsFinal);
6441 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6442 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6443 for(int i=0;i<nbOfCastsFinal;i++)
6445 int castId=castsPresent->getIJ(i,0);
6446 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6447 idsInPflPerType2.push_back(tmp3);
6448 code[3*i]=(int)types[castId];
6449 code[3*i+1]=tmp3->getNumberOfTuples();
6450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6451 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6453 tmp4->copyStringInfoFrom(*profile);
6454 idsPerType2.push_back(tmp4);
6455 code[3*i+2]=(int)idsPerType2.size()-1;
6462 std::size_t sz2=idsInPflPerType2.size();
6463 idsInPflPerType.resize(sz2);
6464 for(std::size_t i=0;i<sz2;i++)
6466 DataArrayInt *locDa=idsInPflPerType2[i];
6468 idsInPflPerType[i]=locDa;
6470 std::size_t sz=idsPerType2.size();
6471 idsPerType.resize(sz);
6472 for(std::size_t i=0;i<sz;i++)
6474 DataArrayInt *locDa=idsPerType2[i];
6476 idsPerType[i]=locDa;
6481 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6482 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6483 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6484 * 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.
6486 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6488 checkFullyDefined();
6489 nM1LevMesh->checkFullyDefined();
6490 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6491 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6492 if(_coords!=nM1LevMesh->getCoords())
6493 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6494 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6495 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6496 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6497 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6498 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6499 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6500 tmp->setConnectivity(tmp0,tmp1);
6501 tmp->renumberCells(ret0->getConstPointer(),false);
6502 revDesc=tmp->getNodalConnectivity();
6503 revDescIndx=tmp->getNodalConnectivityIndex();
6504 DataArrayInt *ret=0;
6505 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6508 ret->getMaxValue(tmp2);
6510 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6511 throw INTERP_KERNEL::Exception(oss.str().c_str());
6516 revDescIndx->incrRef();
6519 meshnM1Old2New=ret0;
6524 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6525 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6526 * in "Old to New" mode.
6527 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6528 * this array using decrRef() as it is no more needed.
6529 * \throw If the nodal connectivity of cells is not defined.
6531 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6533 checkConnectivityFullyDefined();
6534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6535 renumberCells(ret->getConstPointer(),false);
6540 * This methods checks that cells are sorted by their types.
6541 * This method makes asumption (no check) that connectivity is correctly set before calling.
6543 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6545 checkFullyDefined();
6546 const int *conn=_nodal_connec->getConstPointer();
6547 const int *connI=_nodal_connec_index->getConstPointer();
6548 int nbOfCells=getNumberOfCells();
6549 std::set<INTERP_KERNEL::NormalizedCellType> types;
6550 for(const int *i=connI;i!=connI+nbOfCells;)
6552 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6553 if(types.find(curType)!=types.end())
6555 types.insert(curType);
6556 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6562 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6563 * The geometric type order is specified by MED file.
6565 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6567 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6569 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6573 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6574 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6575 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6576 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6578 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6580 checkFullyDefined();
6581 const int *conn=_nodal_connec->getConstPointer();
6582 const int *connI=_nodal_connec_index->getConstPointer();
6583 int nbOfCells=getNumberOfCells();
6587 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6588 for(const int *i=connI;i!=connI+nbOfCells;)
6590 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6591 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6592 if(isTypeExists!=orderEnd)
6594 int pos=(int)std::distance(orderBg,isTypeExists);
6598 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6602 if(sg.find(curType)==sg.end())
6604 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6615 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6616 * 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
6617 * 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'.
6619 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6621 checkConnectivityFullyDefined();
6622 int nbOfCells=getNumberOfCells();
6623 const int *conn=_nodal_connec->getConstPointer();
6624 const int *connI=_nodal_connec_index->getConstPointer();
6625 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6627 tmpa->alloc(nbOfCells,1);
6628 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6629 tmpb->fillWithZero();
6630 int *tmp=tmpa->getPointer();
6631 int *tmp2=tmpb->getPointer();
6632 for(const int *i=connI;i!=connI+nbOfCells;i++)
6634 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6637 int pos=(int)std::distance(orderBg,where);
6639 tmp[std::distance(connI,i)]=pos;
6643 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6644 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6645 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6646 throw INTERP_KERNEL::Exception(oss.str().c_str());
6649 nbPerType=tmpb.retn();
6654 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6656 * \return a new object containing the old to new correspondance.
6658 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6660 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6662 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6666 * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
6667 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6668 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6669 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6671 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6673 DataArrayInt *nbPerType=0;
6674 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6675 nbPerType->decrRef();
6676 return tmpa->buildPermArrPerLevel();
6680 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6681 * The number of cells remains unchanged after the call of this method.
6682 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6683 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6685 * \return the array giving the correspondance old to new.
6687 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6689 checkFullyDefined();
6691 const int *conn=_nodal_connec->getConstPointer();
6692 const int *connI=_nodal_connec_index->getConstPointer();
6693 int nbOfCells=getNumberOfCells();
6694 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6695 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6696 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6698 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6699 types.push_back(curType);
6700 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6702 DataArrayInt *ret=DataArrayInt::New();
6703 ret->alloc(nbOfCells,1);
6704 int *retPtr=ret->getPointer();
6705 std::fill(retPtr,retPtr+nbOfCells,-1);
6707 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6709 for(const int *i=connI;i!=connI+nbOfCells;i++)
6710 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6711 retPtr[std::distance(connI,i)]=newCellId++;
6713 renumberCells(retPtr,false);
6718 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6719 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6720 * This method makes asumption that connectivity is correctly set before calling.
6722 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6724 checkConnectivityFullyDefined();
6725 const int *conn=_nodal_connec->getConstPointer();
6726 const int *connI=_nodal_connec_index->getConstPointer();
6727 int nbOfCells=getNumberOfCells();
6728 std::vector<MEDCouplingUMesh *> ret;
6729 for(const int *i=connI;i!=connI+nbOfCells;)
6731 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6732 int beginCellId=(int)std::distance(connI,i);
6733 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6734 int endCellId=(int)std::distance(connI,i);
6735 int sz=endCellId-beginCellId;
6736 int *cells=new int[sz];
6737 for(int j=0;j<sz;j++)
6738 cells[j]=beginCellId+j;
6739 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6747 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6748 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6749 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6751 * \return a newly allocated instance, that the caller must manage.
6752 * \throw If \a this contains more than one geometric type.
6753 * \throw If the nodal connectivity of \a this is not fully defined.
6754 * \throw If the internal data is not coherent.
6756 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6758 checkConnectivityFullyDefined();
6759 if(_types.size()!=1)
6760 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6761 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6762 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6763 ret->setCoords(getCoords());
6764 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6767 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6768 retC->setNodalConnectivity(c);
6772 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6774 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6775 DataArrayInt *c=0,*ci=0;
6776 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6778 retD->setNodalConnectivity(cs,cis);
6783 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6785 checkConnectivityFullyDefined();
6786 if(_types.size()!=1)
6787 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6788 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6789 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6792 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6793 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6794 throw INTERP_KERNEL::Exception(oss.str().c_str());
6796 int nbCells=getNumberOfCells();
6798 int nbNodesPerCell=(int)cm.getNumberOfNodes();
6799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6800 int *outPtr=connOut->getPointer();
6801 const int *conn=_nodal_connec->begin();
6802 const int *connI=_nodal_connec_index->begin();
6804 for(int i=0;i<nbCells;i++,connI++)
6806 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6807 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6810 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6811 throw INTERP_KERNEL::Exception(oss.str().c_str());
6814 return connOut.retn();
6817 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6819 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6820 checkConnectivityFullyDefined();
6821 if(_types.size()!=1)
6822 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6823 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6825 throw INTERP_KERNEL::Exception(msg0);
6826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6827 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6828 int *cp(c->getPointer()),*cip(ci->getPointer());
6829 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6831 for(int i=0;i<nbCells;i++,cip++,incip++)
6833 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6834 int delta(stop-strt);
6837 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6838 cp=std::copy(incp+strt,incp+stop,cp);
6840 throw INTERP_KERNEL::Exception(msg0);
6843 throw INTERP_KERNEL::Exception(msg0);
6844 cip[1]=cip[0]+delta;
6846 nodalConn=c.retn(); nodalConnIndex=ci.retn();
6850 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6851 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6852 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6853 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6854 * are not used here to avoid the build of big permutation array.
6856 * \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
6857 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6858 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6859 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6860 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6861 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6862 * \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
6863 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6865 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6866 DataArrayInt *&szOfCellGrpOfSameType,
6867 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6869 std::vector<const MEDCouplingUMesh *> ms2;
6870 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6873 (*it)->checkConnectivityFullyDefined();
6877 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6878 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6879 int meshDim=ms2[0]->getMeshDimension();
6880 std::vector<const MEDCouplingUMesh *> m1ssm;
6881 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6883 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6884 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6887 ret1->alloc(0,1); ret2->alloc(0,1);
6888 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6890 if(meshDim!=(*it)->getMeshDimension())
6891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6892 if(refCoo!=(*it)->getCoords())
6893 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6894 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6895 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6896 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6897 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6899 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6900 m1ssmSingleAuto.push_back(singleCell);
6901 m1ssmSingle.push_back(singleCell);
6902 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6905 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6907 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6908 for(std::size_t i=0;i<m1ssm.size();i++)
6909 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6910 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6911 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6912 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6917 * This method returns a newly created DataArrayInt instance.
6918 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6920 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6922 checkFullyDefined();
6923 const int *conn=_nodal_connec->getConstPointer();
6924 const int *connIndex=_nodal_connec_index->getConstPointer();
6925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6926 for(const int *w=begin;w!=end;w++)
6927 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6928 ret->pushBackSilent(*w);
6933 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6934 * are in [0:getNumberOfCells())
6936 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6938 checkFullyDefined();
6939 const int *conn=_nodal_connec->getConstPointer();
6940 const int *connI=_nodal_connec_index->getConstPointer();
6941 int nbOfCells=getNumberOfCells();
6942 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6943 int *tmp=new int[nbOfCells];
6944 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6947 for(const int *i=connI;i!=connI+nbOfCells;i++)
6948 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6949 tmp[std::distance(connI,i)]=j++;
6951 DataArrayInt *ret=DataArrayInt::New();
6952 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6953 ret->copyStringInfoFrom(*da);
6954 int *retPtr=ret->getPointer();
6955 const int *daPtr=da->getConstPointer();
6956 int nbOfElems=da->getNbOfElems();
6957 for(int k=0;k<nbOfElems;k++)
6958 retPtr[k]=tmp[daPtr[k]];
6964 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6965 * This method \b works \b for mesh sorted by type.
6966 * cells whose ids is in 'idsPerGeoType' array.
6967 * This method conserves coords and name of mesh.
6969 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6971 std::vector<int> code=getDistributionOfTypes();
6972 std::size_t nOfTypesInThis=code.size()/3;
6973 int sz=0,szOfType=0;
6974 for(std::size_t i=0;i<nOfTypesInThis;i++)
6979 szOfType=code[3*i+1];
6981 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6982 if(*work<0 || *work>=szOfType)
6984 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6985 oss << ". It should be in [0," << szOfType << ") !";
6986 throw INTERP_KERNEL::Exception(oss.str().c_str());
6988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6989 int *idsPtr=idsTokeep->getPointer();
6991 for(std::size_t i=0;i<nOfTypesInThis;i++)
6994 for(int j=0;j<code[3*i+1];j++)
6997 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6998 offset+=code[3*i+1];
7000 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7001 ret->copyTinyInfoFrom(this);
7006 * This method returns a vector of size 'this->getNumberOfCells()'.
7007 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7009 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7011 int ncell=getNumberOfCells();
7012 std::vector<bool> ret(ncell);
7013 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7014 const int *c=getNodalConnectivity()->getConstPointer();
7015 for(int i=0;i<ncell;i++)
7017 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7018 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7019 ret[i]=cm.isQuadratic();
7025 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7027 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7029 if(other->getType()!=UNSTRUCTURED)
7030 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7031 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7032 return MergeUMeshes(this,otherC);
7036 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7037 * computed by averaging coordinates of cell nodes, so this method is not a right
7038 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7039 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7040 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7041 * components. The caller is to delete this array using decrRef() as it is
7043 * \throw If the coordinates array is not set.
7044 * \throw If the nodal connectivity of cells is not defined.
7045 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7047 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7049 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7050 int spaceDim=getSpaceDimension();
7051 int nbOfCells=getNumberOfCells();
7052 ret->alloc(nbOfCells,spaceDim);
7053 ret->copyStringInfoFrom(*getCoords());
7054 double *ptToFill=ret->getPointer();
7055 const int *nodal=_nodal_connec->getConstPointer();
7056 const int *nodalI=_nodal_connec_index->getConstPointer();
7057 const double *coor=_coords->getConstPointer();
7058 for(int i=0;i<nbOfCells;i++)
7060 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7061 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7068 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7069 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7071 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7072 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7074 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7075 * \throw If \a this is not fully defined (coordinates and connectivity)
7076 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7078 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7080 checkFullyDefined();
7081 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7082 int spaceDim=getSpaceDimension();
7083 int nbOfCells=getNumberOfCells();
7084 int nbOfNodes=getNumberOfNodes();
7085 ret->alloc(nbOfCells,spaceDim);
7086 double *ptToFill=ret->getPointer();
7087 const int *nodal=_nodal_connec->getConstPointer();
7088 const int *nodalI=_nodal_connec_index->getConstPointer();
7089 const double *coor=_coords->getConstPointer();
7090 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7092 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7093 std::fill(ptToFill,ptToFill+spaceDim,0.);
7094 if(type!=INTERP_KERNEL::NORM_POLYHED)
7096 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7098 if(*conn>=0 && *conn<nbOfNodes)
7099 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7102 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7103 throw INTERP_KERNEL::Exception(oss.str().c_str());
7106 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7107 if(nbOfNodesInCell>0)
7108 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7111 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7112 throw INTERP_KERNEL::Exception(oss.str().c_str());
7117 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7119 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7121 if(*it>=0 && *it<nbOfNodes)
7122 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7125 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7126 throw INTERP_KERNEL::Exception(oss.str().c_str());
7130 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7133 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7134 throw INTERP_KERNEL::Exception(oss.str().c_str());
7142 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7143 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7144 * are specified via an array of cell ids.
7145 * \warning Validity of the specified cell ids is not checked!
7146 * Valid range is [ 0, \a this->getNumberOfCells() ).
7147 * \param [in] begin - an array of cell ids of interest.
7148 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7149 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7150 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7151 * caller is to delete this array using decrRef() as it is no more needed.
7152 * \throw If the coordinates array is not set.
7153 * \throw If the nodal connectivity of cells is not defined.
7155 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7156 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7158 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7160 DataArrayDouble *ret=DataArrayDouble::New();
7161 int spaceDim=getSpaceDimension();
7162 int nbOfTuple=(int)std::distance(begin,end);
7163 ret->alloc(nbOfTuple,spaceDim);
7164 double *ptToFill=ret->getPointer();
7165 double *tmp=new double[spaceDim];
7166 const int *nodal=_nodal_connec->getConstPointer();
7167 const int *nodalI=_nodal_connec_index->getConstPointer();
7168 const double *coor=_coords->getConstPointer();
7169 for(const int *w=begin;w!=end;w++)
7171 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7172 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7180 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7183 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7187 da->checkAllocated();
7188 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7190 int nbOfTuples=da->getNumberOfTuples();
7191 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7192 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7193 c->alloc(2*nbOfTuples,1);
7194 cI->alloc(nbOfTuples+1,1);
7195 int *cp=c->getPointer();
7196 int *cip=cI->getPointer();
7198 for(int i=0;i<nbOfTuples;i++)
7200 *cp++=INTERP_KERNEL::NORM_POINT1;
7204 ret->setConnectivity(c,cI,true);
7208 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7209 * Cells and nodes of
7210 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7211 * \param [in] mesh1 - the first mesh.
7212 * \param [in] mesh2 - the second mesh.
7213 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7214 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7215 * is no more needed.
7216 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7217 * \throw If the coordinates array is not set in none of the meshes.
7218 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7219 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7221 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7223 std::vector<const MEDCouplingUMesh *> tmp(2);
7224 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7225 return MergeUMeshes(tmp);
7229 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7230 * Cells and nodes of
7231 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7232 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7233 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7234 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7235 * is no more needed.
7236 * \throw If \a a.size() == 0.
7237 * \throw If \a a[ *i* ] == NULL.
7238 * \throw If the coordinates array is not set in none of the meshes.
7239 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7240 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7242 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7244 std::size_t sz=a.size();
7246 return MergeUMeshesLL(a);
7247 for(std::size_t ii=0;ii<sz;ii++)
7250 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7251 throw INTERP_KERNEL::Exception(oss.str().c_str());
7253 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7254 std::vector< const MEDCouplingUMesh * > aa(sz);
7256 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7258 const MEDCouplingUMesh *cur=a[i];
7259 const DataArrayDouble *coo=cur->getCoords();
7261 spaceDim=coo->getNumberOfComponents();
7264 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7265 for(std::size_t i=0;i<sz;i++)
7267 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7270 return MergeUMeshesLL(aa);
7275 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7278 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7279 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7280 int meshDim=(*it)->getMeshDimension();
7281 int nbOfCells=(*it)->getNumberOfCells();
7282 int meshLgth=(*it++)->getMeshLength();
7283 for(;it!=a.end();it++)
7285 if(meshDim!=(*it)->getMeshDimension())
7286 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7287 nbOfCells+=(*it)->getNumberOfCells();
7288 meshLgth+=(*it)->getMeshLength();
7290 std::vector<const MEDCouplingPointSet *> aps(a.size());
7291 std::copy(a.begin(),a.end(),aps.begin());
7292 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7293 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7294 ret->setCoords(pts);
7295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7296 c->alloc(meshLgth,1);
7297 int *cPtr=c->getPointer();
7298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7299 cI->alloc(nbOfCells+1,1);
7300 int *cIPtr=cI->getPointer();
7304 for(it=a.begin();it!=a.end();it++)
7306 int curNbOfCell=(*it)->getNumberOfCells();
7307 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7308 const int *curC=(*it)->_nodal_connec->getConstPointer();
7309 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7310 for(int j=0;j<curNbOfCell;j++)
7312 const int *src=curC+curCI[j];
7314 for(;src!=curC+curCI[j+1];src++,cPtr++)
7322 offset+=curCI[curNbOfCell];
7323 offset2+=(*it)->getNumberOfNodes();
7326 ret->setConnectivity(c,cI,true);
7333 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7334 * dimension and sharing the node coordinates array.
7335 * All cells of the first mesh precede all cells of the second mesh
7336 * within the result mesh.
7337 * \param [in] mesh1 - the first mesh.
7338 * \param [in] mesh2 - the second mesh.
7339 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7340 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7341 * is no more needed.
7342 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7343 * \throw If the meshes do not share the node coordinates array.
7344 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7345 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7347 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7349 std::vector<const MEDCouplingUMesh *> tmp(2);
7350 tmp[0]=mesh1; tmp[1]=mesh2;
7351 return MergeUMeshesOnSameCoords(tmp);
7355 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7356 * dimension and sharing the node coordinates array.
7357 * All cells of the *i*-th mesh precede all cells of the
7358 * (*i*+1)-th mesh within the result mesh.
7359 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7360 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7361 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7362 * is no more needed.
7363 * \throw If \a a.size() == 0.
7364 * \throw If \a a[ *i* ] == NULL.
7365 * \throw If the meshes do not share the node coordinates array.
7366 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7367 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7369 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7372 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7373 for(std::size_t ii=0;ii<meshes.size();ii++)
7376 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7377 throw INTERP_KERNEL::Exception(oss.str().c_str());
7379 const DataArrayDouble *coords=meshes.front()->getCoords();
7380 int meshDim=meshes.front()->getMeshDimension();
7381 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7383 int meshIndexLgth=0;
7384 for(;iter!=meshes.end();iter++)
7386 if(coords!=(*iter)->getCoords())
7387 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7388 if(meshDim!=(*iter)->getMeshDimension())
7389 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7390 meshLgth+=(*iter)->getMeshLength();
7391 meshIndexLgth+=(*iter)->getNumberOfCells();
7393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7394 nodal->alloc(meshLgth,1);
7395 int *nodalPtr=nodal->getPointer();
7396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7397 nodalIndex->alloc(meshIndexLgth+1,1);
7398 int *nodalIndexPtr=nodalIndex->getPointer();
7400 for(iter=meshes.begin();iter!=meshes.end();iter++)
7402 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7403 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7404 int nbOfCells=(*iter)->getNumberOfCells();
7405 int meshLgth2=(*iter)->getMeshLength();
7406 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7407 if(iter!=meshes.begin())
7408 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7410 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7413 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7414 ret->setName("merge");
7415 ret->setMeshDimension(meshDim);
7416 ret->setConnectivity(nodal,nodalIndex,true);
7417 ret->setCoords(coords);
7422 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7423 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7424 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7425 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7426 * New" mode are returned for each input mesh.
7427 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7428 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7429 * valid values [0,1,2], see zipConnectivityTraducer().
7430 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7431 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7432 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7434 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7435 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7436 * is no more needed.
7437 * \throw If \a meshes.size() == 0.
7438 * \throw If \a meshes[ *i* ] == NULL.
7439 * \throw If the meshes do not share the node coordinates array.
7440 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7441 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7442 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7443 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7445 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7447 //All checks are delegated to MergeUMeshesOnSameCoords
7448 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7450 corr.resize(meshes.size());
7451 std::size_t nbOfMeshes=meshes.size();
7453 const int *o2nPtr=o2n->getConstPointer();
7454 for(std::size_t i=0;i<nbOfMeshes;i++)
7456 DataArrayInt *tmp=DataArrayInt::New();
7457 int curNbOfCells=meshes[i]->getNumberOfCells();
7458 tmp->alloc(curNbOfCells,1);
7459 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7460 offset+=curNbOfCells;
7461 tmp->setName(meshes[i]->getName().c_str());
7468 * Makes all given meshes share the nodal connectivity array. The common connectivity
7469 * array is created by concatenating the connectivity arrays of all given meshes. All
7470 * the given meshes must be of the same space dimension but dimension of cells **can
7471 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7472 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7473 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7474 * \param [in,out] meshes - a vector of meshes to update.
7475 * \throw If any of \a meshes is NULL.
7476 * \throw If the coordinates array is not set in any of \a meshes.
7477 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7478 * \throw If \a meshes are of different space dimension.
7480 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7482 std::size_t sz=meshes.size();
7485 std::vector< const DataArrayDouble * > coords(meshes.size());
7486 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7487 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7491 (*it)->checkConnectivityFullyDefined();
7492 const DataArrayDouble *coo=(*it)->getCoords();
7497 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7498 oss << " has no coordinate array defined !";
7499 throw INTERP_KERNEL::Exception(oss.str().c_str());
7504 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7505 oss << " is null !";
7506 throw INTERP_KERNEL::Exception(oss.str().c_str());
7509 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7510 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7511 int offset=(*it)->getNumberOfNodes();
7512 (*it++)->setCoords(res);
7513 for(;it!=meshes.end();it++)
7515 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7516 (*it)->setCoords(res);
7517 (*it)->shiftNodeNumbersInConn(offset);
7518 offset+=oldNumberOfNodes;
7523 * Merges nodes coincident with a given precision within all given meshes that share
7524 * the nodal connectivity array. The given meshes **can be of different** mesh
7525 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7526 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7527 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7528 * \param [in,out] meshes - a vector of meshes to update.
7529 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7530 * \throw If any of \a meshes is NULL.
7531 * \throw If the \a meshes do not share the same node coordinates array.
7532 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7534 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7538 std::set<const DataArrayDouble *> s;
7539 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7542 s.insert((*it)->getCoords());
7545 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 !";
7546 throw INTERP_KERNEL::Exception(oss.str().c_str());
7551 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 !";
7552 throw INTERP_KERNEL::Exception(oss.str().c_str());
7554 const DataArrayDouble *coo=*(s.begin());
7558 DataArrayInt *comm,*commI;
7559 coo->findCommonTuples(eps,-1,comm,commI);
7560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7561 int oldNbOfNodes=coo->getNumberOfTuples();
7563 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7564 if(oldNbOfNodes==newNbOfNodes)
7566 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7567 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7569 (*it)->renumberNodesInConn(o2n->getConstPointer());
7570 (*it)->setCoords(newCoords);
7575 * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret.
7576 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7577 * \param isQuad specifies the policy of connectivity.
7578 * @ret in/out parameter in which the result will be append
7580 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7582 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7583 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7584 ret.push_back(cm.getExtrudedType());
7585 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7588 case INTERP_KERNEL::NORM_POINT1:
7590 ret.push_back(connBg[1]);
7591 ret.push_back(connBg[1]+nbOfNodesPerLev);
7594 case INTERP_KERNEL::NORM_SEG2:
7596 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7597 ret.insert(ret.end(),conn,conn+4);
7600 case INTERP_KERNEL::NORM_SEG3:
7602 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7603 ret.insert(ret.end(),conn,conn+8);
7606 case INTERP_KERNEL::NORM_QUAD4:
7608 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7609 ret.insert(ret.end(),conn,conn+8);
7612 case INTERP_KERNEL::NORM_TRI3:
7614 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7615 ret.insert(ret.end(),conn,conn+6);
7618 case INTERP_KERNEL::NORM_TRI6:
7620 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,
7621 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7622 ret.insert(ret.end(),conn,conn+15);
7625 case INTERP_KERNEL::NORM_QUAD8:
7628 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7629 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7630 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7632 ret.insert(ret.end(),conn,conn+20);
7635 case INTERP_KERNEL::NORM_POLYGON:
7637 std::back_insert_iterator< std::vector<int> > ii(ret);
7638 std::copy(connBg+1,connEnd,ii);
7640 std::reverse_iterator<const int *> rConnBg(connEnd);
7641 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7642 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7643 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7644 for(std::size_t i=0;i<nbOfRadFaces;i++)
7647 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7648 std::copy(conn,conn+4,ii);
7653 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7658 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7660 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7662 double v[3]={0.,0.,0.};
7663 std::size_t sz=std::distance(begin,end);
7666 for(std::size_t i=0;i<sz;i++)
7668 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];
7669 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7670 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7672 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7676 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7678 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7680 std::vector<std::pair<int,int> > edges;
7681 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7682 const int *bgFace=begin;
7683 for(std::size_t i=0;i<nbOfFaces;i++)
7685 const int *endFace=std::find(bgFace+1,end,-1);
7686 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7687 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7689 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7690 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7692 edges.push_back(p1);
7696 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7700 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7702 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7704 double vec0[3],vec1[3];
7705 std::size_t sz=std::distance(begin,end);
7707 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7708 int nbOfNodes=(int)sz/2;
7709 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7710 const double *pt0=coords+3*begin[0];
7711 const double *pt1=coords+3*begin[nbOfNodes];
7712 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7713 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7716 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7718 std::size_t sz=std::distance(begin,end);
7719 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7720 std::size_t nbOfNodes(sz/2);
7721 std::copy(begin,end,(int *)tmp);
7722 for(std::size_t j=1;j<nbOfNodes;j++)
7724 begin[j]=tmp[nbOfNodes-j];
7725 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7729 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7731 std::size_t sz=std::distance(begin,end);
7733 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7734 double vec0[3],vec1[3];
7735 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7736 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];
7737 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;
7740 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7742 std::size_t sz=std::distance(begin,end);
7744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7746 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7747 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7748 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7752 * 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 )
7753 * 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
7756 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7757 * \param [in] coords the coordinates with nb of components exactly equal to 3
7758 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7759 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7760 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7762 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7764 int nbFaces=std::count(begin+1,end,-1)+1;
7765 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7766 double *vPtr=v->getPointer();
7767 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7768 double *pPtr=p->getPointer();
7769 const int *stFaceConn=begin+1;
7770 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7772 const int *endFaceConn=std::find(stFaceConn,end,-1);
7773 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7774 stFaceConn=endFaceConn+1;
7776 pPtr=p->getPointer(); vPtr=v->getPointer();
7777 DataArrayInt *comm1=0,*commI1=0;
7778 v->findCommonTuples(eps,-1,comm1,commI1);
7779 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7780 const int *comm1Ptr=comm1->getConstPointer();
7781 const int *commI1Ptr=commI1->getConstPointer();
7782 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7783 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7785 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7786 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7787 mm->finishInsertingCells();
7789 for(int i=0;i<nbOfGrps1;i++)
7791 int vecId=comm1Ptr[commI1Ptr[i]];
7792 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7793 DataArrayInt *comm2=0,*commI2=0;
7794 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7795 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7796 const int *comm2Ptr=comm2->getConstPointer();
7797 const int *commI2Ptr=commI2->getConstPointer();
7798 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7799 for(int j=0;j<nbOfGrps2;j++)
7801 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7803 res->insertAtTheEnd(begin,end);
7804 res->pushBackSilent(-1);
7808 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7810 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7811 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7812 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7813 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7816 const int *idsNodePtr=idsNode->getConstPointer();
7817 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];
7818 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7819 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7820 if(std::abs(norm)>eps)
7822 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7823 mm3->rotate(center,vec,angle);
7825 mm3->changeSpaceDimension(2);
7826 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7827 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7828 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7829 int nbOfCells=mm4->getNumberOfCells();
7830 for(int k=0;k<nbOfCells;k++)
7833 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7834 res->pushBackSilent(idsNodePtr[*work]);
7835 res->pushBackSilent(-1);
7840 res->popBackSilent();
7844 * 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
7845 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7847 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7848 * \param [in] coords coordinates expected to have 3 components.
7849 * \param [in] begin start of the nodal connectivity of the face.
7850 * \param [in] end end of the nodal connectivity (excluded) of the face.
7851 * \param [out] v the normalized vector of size 3
7852 * \param [out] p the pos of plane
7854 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7856 std::size_t nbPoints=std::distance(begin,end);
7858 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7859 double vec[3]={0.,0.,0.};
7861 bool refFound=false;
7862 for(;j<nbPoints-1 && !refFound;j++)
7864 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7865 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7866 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7867 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7871 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7874 for(std::size_t i=j;i<nbPoints-1;i++)
7877 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7878 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7879 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7880 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7883 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7884 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];
7885 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7888 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7889 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7893 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7897 * This method tries to obtain a well oriented polyhedron.
7898 * If the algorithm fails, an exception will be thrown.
7900 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7902 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7903 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7904 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7906 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7907 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7908 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7910 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7913 std::size_t smthChanged=0;
7914 for(std::size_t i=0;i<nbOfFaces;i++)
7916 endFace=std::find(bgFace+1,end,-1);
7917 nbOfEdgesInFace=std::distance(bgFace,endFace);
7921 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7923 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7924 std::pair<int,int> p2(p1.second,p1.first);
7925 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7926 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7927 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7932 std::reverse(bgFace+1,endFace);
7933 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7935 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7936 std::pair<int,int> p2(p1.second,p1.first);
7937 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7938 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7939 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7940 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7941 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7942 if(it!=edgesOK.end())
7945 edgesFinished.push_back(p1);
7948 edgesOK.push_back(p1);
7955 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7957 if(!edgesOK.empty())
7958 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7959 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7960 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7962 for(std::size_t i=0;i<nbOfFaces;i++)
7964 endFace=std::find(bgFace+1,end,-1);
7965 std::reverse(bgFace+1,endFace);
7972 * This method makes the assumption spacedimension == meshdimension == 2.
7973 * This method works only for linear cells.
7975 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7977 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7979 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7980 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7981 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7983 int nbOfNodesExpected=m->getNumberOfNodes();
7984 if(m->getNumberOfCells()!=nbOfNodesExpected)
7985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7987 const int *n2oPtr=n2o->getConstPointer();
7988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7989 m->getReverseNodalConnectivity(revNodal,revNodalI);
7990 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7991 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7992 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7994 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7995 if(nbOfNodesExpected<1)
7998 int prevNode=nodalPtr[nodalIPtr[0]+1];
7999 *work++=n2oPtr[prevNode];
8000 for(int i=1;i<nbOfNodesExpected;i++)
8002 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8004 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8005 conn.erase(prevNode);
8008 int curNode=*(conn.begin());
8009 *work++=n2oPtr[curNode];
8010 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8011 shar.erase(prevCell);
8014 prevCell=*(shar.begin());
8018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8021 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8024 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8030 * This method makes the assumption spacedimension == meshdimension == 3.
8031 * This method works only for linear cells.
8033 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8035 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8037 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8038 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8039 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8040 const int *conn=m->getNodalConnectivity()->getConstPointer();
8041 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8042 int nbOfCells=m->getNumberOfCells();
8043 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8044 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8047 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8048 for(int i=1;i<nbOfCells;i++)
8051 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8057 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8058 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8060 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8064 for(int i=0;i<nbOfNodesInCell;i++)
8065 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8066 else if(spaceDim==2)
8068 for(int i=0;i<nbOfNodesInCell;i++)
8070 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8075 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8078 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const throw(INTERP_KERNEL::Exception)
8080 int nbOfCells=getNumberOfCells();
8082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8083 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};
8084 ofs << " <" << getVTKDataSetType() << ">\n";
8085 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8086 ofs << " <PointData>\n" << pointData << std::endl;
8087 ofs << " </PointData>\n";
8088 ofs << " <CellData>\n" << cellData << std::endl;
8089 ofs << " </CellData>\n";
8090 ofs << " <Points>\n";
8091 if(getSpaceDimension()==3)
8092 _coords->writeVTK(ofs,8,"Points",byteData);
8095 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8096 coo->writeVTK(ofs,8,"Points",byteData);
8098 ofs << " </Points>\n";
8099 ofs << " <Cells>\n";
8100 const int *cPtr=_nodal_connec->getConstPointer();
8101 const int *cIPtr=_nodal_connec_index->getConstPointer();
8102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8106 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8107 int szFaceOffsets=0,szConn=0;
8108 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8111 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8114 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8115 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8119 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8120 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8121 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8122 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8123 w4=std::copy(c.begin(),c.end(),w4);
8126 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8127 types->writeVTK(ofs,8,"UInt8","types",byteData);
8128 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8129 if(szFaceOffsets!=0)
8130 {//presence of Polyhedra
8131 connectivity->reAlloc(szConn);
8132 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8134 w1=faces->getPointer();
8135 for(int i=0;i<nbOfCells;i++)
8136 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8138 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8140 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8141 for(int j=0;j<nbFaces;j++)
8143 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8144 *w1++=(int)std::distance(w6,w5);
8145 w1=std::copy(w6,w5,w1);
8149 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8151 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8152 ofs << " </Cells>\n";
8153 ofs << " </Piece>\n";
8154 ofs << " </" << getVTKDataSetType() << ">\n";
8157 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8159 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8161 { stream << " Not set !"; return ; }
8162 stream << " Mesh dimension : " << _mesh_dim << ".";
8166 { stream << " No coordinates set !"; return ; }
8167 if(!_coords->isAllocated())
8168 { stream << " Coordinates set but not allocated !"; return ; }
8169 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8170 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8171 if(!_nodal_connec_index)
8172 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8173 if(!_nodal_connec_index->isAllocated())
8174 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8175 int lgth=_nodal_connec_index->getNumberOfTuples();
8176 int cpt=_nodal_connec_index->getNumberOfComponents();
8177 if(cpt!=1 || lgth<1)
8179 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8182 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8184 return std::string("UnstructuredGrid");
8188 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8189 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8190 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8192 * \param [in] m1 - the first input mesh which is a partitioned object.
8193 * \param [in] m2 - the second input mesh which is a partition tool.
8194 * \param [in] eps - precision used to detect coincident mesh entities.
8195 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8196 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8197 * this array using decrRef() as it is no more needed.
8198 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8199 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8200 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8201 * any cell of \a m2. The caller is to delete this array using decrRef() as
8202 * it is no more needed.
8203 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8204 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8205 * is no more needed.
8206 * \throw If the coordinates array is not set in any of the meshes.
8207 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8208 * \throw If any of the meshes is not a 2D mesh in 2D space.
8210 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8212 m1->checkFullyDefined();
8213 m2->checkFullyDefined();
8214 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8215 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8216 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8217 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8218 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8219 std::vector<double> addCoo,addCoordsQuadratic;
8220 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8221 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8222 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8223 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8224 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8225 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8226 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8227 std::vector< std::vector<int> > intersectEdge2;
8228 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8229 subDiv2.clear(); dd5=0; dd6=0;
8230 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8231 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8232 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8233 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8235 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8236 addCooDa->alloc((int)(addCoo.size())/2,2);
8237 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8238 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8239 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8240 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8241 std::vector<const DataArrayDouble *> coordss(4);
8242 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8243 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8244 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8249 ret->setConnectivity(conn,connI,true);
8250 ret->setCoords(coo);
8251 cellNb1=c1.retn(); cellNb2=c2.retn();
8255 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8256 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8257 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8258 const std::vector<double>& addCoords,
8259 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8261 static const int SPACEDIM=2;
8262 const double *coo1=m1->getCoords()->getConstPointer();
8263 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8264 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8265 int offset1=m1->getNumberOfNodes();
8266 const double *coo2=m2->getCoords()->getConstPointer();
8267 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8268 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8269 int offset2=offset1+m2->getNumberOfNodes();
8270 int offset3=offset2+((int)addCoords.size())/2;
8271 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8272 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8273 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8274 int ncell1=m1->getNumberOfCells();
8276 for(int i=0;i<ncell1;i++)
8278 std::vector<int> candidates2;
8279 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8280 std::map<INTERP_KERNEL::Node *,int> mapp;
8281 std::map<int,INTERP_KERNEL::Node *> mappRev;
8282 INTERP_KERNEL::QuadraticPolygon pol1;
8283 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8284 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8285 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8286 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8287 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8289 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
8290 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8291 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8292 for(it1.first();!it1.finished();it1.next())
8293 edges1.insert(it1.current()->getPtr());
8295 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8296 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8298 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8300 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8301 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8302 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8303 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8304 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8307 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8309 pol1.initLocationsWithOther(pol2s[ii]);
8310 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8311 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8312 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8318 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8320 catch(INTERP_KERNEL::Exception& e)
8322 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();
8323 throw INTERP_KERNEL::Exception(oss.str().c_str());
8326 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8327 (*it).second->decrRef();
8332 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8335 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8336 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8337 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8338 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8339 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8341 static const int SPACEDIM=2;
8342 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8343 desc2=DataArrayInt::New();
8344 descIndx2=DataArrayInt::New();
8345 revDesc2=DataArrayInt::New();
8346 revDescIndx2=DataArrayInt::New();
8347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8349 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8350 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8351 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8352 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8353 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8354 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8355 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8356 int ncell1=m1Desc->getNumberOfCells();
8357 int ncell2=m2Desc->getNumberOfCells();
8358 intersectEdge1.resize(ncell1);
8359 colinear2.resize(ncell2);
8360 subDiv2.resize(ncell2);
8361 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8362 std::vector<int> candidates1(1);
8363 int offset1=m1->getNumberOfNodes();
8364 int offset2=offset1+m2->getNumberOfNodes();
8365 for(int i=0;i<ncell1;i++)
8367 std::vector<int> candidates2;
8368 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8369 if(!candidates2.empty())
8371 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8372 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8374 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8375 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8380 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8382 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8383 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8387 * This method performs the 2nd step of Partition of 2D mesh.
8388 * This method has 4 inputs :
8389 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8390 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8391 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8392 * 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'
8393 * \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'
8394 * \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.
8395 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8397 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)
8399 int offset1=m1->getNumberOfNodes();
8400 int ncell=m2->getNumberOfCells();
8401 const int *c=m2->getNodalConnectivity()->getConstPointer();
8402 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8403 const double *coo=m2->getCoords()->getConstPointer();
8404 const double *cooBis=m1->getCoords()->getConstPointer();
8405 int offset2=offset1+m2->getNumberOfNodes();
8406 intersectEdge.resize(ncell);
8407 for(int i=0;i<ncell;i++,cI++)
8409 const std::vector<int>& divs=subDiv[i];
8410 int nnode=cI[1]-cI[0]-1;
8411 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8412 std::map<INTERP_KERNEL::Node *, int> mapp22;
8413 for(int j=0;j<nnode;j++)
8415 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8416 int nnid=c[(*cI)+j+1];
8417 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8418 mapp22[nn]=nnid+offset1;
8420 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8421 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8422 ((*it).second.first)->decrRef();
8423 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8424 std::map<INTERP_KERNEL::Node *,int> mapp3;
8425 for(std::size_t j=0;j<divs.size();j++)
8428 INTERP_KERNEL::Node *tmp=0;
8430 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8432 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8434 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8438 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8439 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8446 * 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).
8447 * 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
8448 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8449 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8450 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8451 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8452 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8453 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8454 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8455 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8456 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8457 * \param [out] cut3DSuf input/output param.
8459 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8460 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8461 const int *desc, const int *descIndx,
8462 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8464 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8465 int nbOf3DSurfCell=(int)cut3DSurf.size();
8466 for(int i=0;i<nbOf3DSurfCell;i++)
8468 std::vector<int> res;
8469 int offset=descIndx[i];
8470 int nbOfSeg=descIndx[i+1]-offset;
8471 for(int j=0;j<nbOfSeg;j++)
8473 int edgeId=desc[offset+j];
8474 int status=cut3DCurve[edgeId];
8478 res.push_back(status);
8481 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8482 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8490 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8496 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8497 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8500 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8504 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8509 {// case when plane is on a multi colinear edge of a polyhedron
8510 if((int)res.size()==2*nbOfSeg)
8512 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8515 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8522 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8523 * 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).
8524 * 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
8525 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8526 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8527 * \param desc is the descending connectivity 3D->3DSurf
8528 * \param descIndx is the descending connectivity index 3D->3DSurf
8530 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8531 const int *desc, const int *descIndx,
8532 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8534 checkFullyDefined();
8535 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8536 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8537 const int *nodal3D=_nodal_connec->getConstPointer();
8538 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8539 int nbOfCells=getNumberOfCells();
8540 for(int i=0;i<nbOfCells;i++)
8542 std::map<int, std::set<int> > m;
8543 int offset=descIndx[i];
8544 int nbOfFaces=descIndx[i+1]-offset;
8547 for(int j=0;j<nbOfFaces;j++)
8549 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8550 if(p.first!=-1 && p.second!=-1)
8554 start=p.first; end=p.second;
8555 m[p.first].insert(p.second);
8556 m[p.second].insert(p.first);
8560 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8561 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8562 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8563 INTERP_KERNEL::NormalizedCellType cmsId;
8564 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8565 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8566 for(unsigned k=0;k<nbOfNodesSon;k++)
8568 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8569 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8576 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8580 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8581 const std::set<int>& s=(*it).second;
8582 std::set<int> s2; s2.insert(prev);
8584 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8587 int val=*s3.begin();
8588 conn.push_back(start);
8595 conn.push_back(end);
8598 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8599 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8600 cellIds->pushBackSilent(i);
8606 * 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
8607 * 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
8608 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8609 * 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
8610 * 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.
8612 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8614 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8616 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8619 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8620 if(cm.getDimension()==2)
8622 const int *node=nodalConnBg+1;
8623 int startNode=*node++;
8624 double refX=coords[2*startNode];
8625 for(;node!=nodalConnEnd;node++)
8627 if(coords[2*(*node)]<refX)
8630 refX=coords[2*startNode];
8633 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8637 double angle0=-M_PI/2;
8642 double angleNext=0.;
8643 while(nextNode!=startNode)
8647 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8649 if(*node!=tmpOut.back() && *node!=prevNode)
8651 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8652 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8657 res=angle0-angleM+2.*M_PI;
8666 if(nextNode!=startNode)
8668 angle0=angleNext-M_PI;
8671 prevNode=tmpOut.back();
8672 tmpOut.push_back(nextNode);
8675 std::vector<int> tmp3(2*(sz-1));
8676 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8677 std::copy(nodalConnBg+1,nodalConnEnd,it);
8678 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8680 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8683 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8685 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8690 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8691 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8696 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8699 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8703 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8704 * 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.
8706 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8707 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8708 * \param [in,out] arr array in which the remove operation will be done.
8709 * \param [in,out] arrIndx array in the remove operation will modify
8710 * \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])
8711 * \return true if \b arr and \b arrIndx have been modified, false if not.
8713 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8715 if(!arrIndx || !arr)
8716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8717 if(offsetForRemoval<0)
8718 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8719 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8720 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8721 int *arrIPtr=arrIndx->getPointer();
8724 const int *arrPtr=arr->getConstPointer();
8725 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8726 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8728 if(*arrIPtr-previousArrI>offsetForRemoval)
8730 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8732 if(s.find(*work)==s.end())
8733 arrOut.push_back(*work);
8736 previousArrI=*arrIPtr;
8737 *arrIPtr=(int)arrOut.size();
8739 if(arr->getNumberOfTuples()==(int)arrOut.size())
8741 arr->alloc((int)arrOut.size(),1);
8742 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8747 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8748 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8749 * The selection of extraction is done standardly in new2old format.
8750 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8752 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8753 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8754 * \param [in] arrIn arr origin array from which the extraction will be done.
8755 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8756 * \param [out] arrOut the resulting array
8757 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8758 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8760 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8761 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8763 if(!arrIn || !arrIndxIn)
8764 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8765 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8766 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8767 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8768 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8769 const int *arrInPtr=arrIn->getConstPointer();
8770 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8771 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8774 int maxSizeOfArr=arrIn->getNumberOfTuples();
8775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8777 arrIo->alloc((int)(sz+1),1);
8778 const int *idsIt=idsOfSelectBg;
8779 int *work=arrIo->getPointer();
8782 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8784 if(*idsIt>=0 && *idsIt<nbOfGrps)
8785 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8788 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8789 throw INTERP_KERNEL::Exception(oss.str().c_str());
8795 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8796 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8797 throw INTERP_KERNEL::Exception(oss.str().c_str());
8800 arro->alloc(lgth,1);
8801 work=arro->getPointer();
8802 idsIt=idsOfSelectBg;
8803 for(std::size_t i=0;i<sz;i++,idsIt++)
8805 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8806 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8809 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8810 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8811 throw INTERP_KERNEL::Exception(oss.str().c_str());
8815 arrIndexOut=arrIo.retn();
8819 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8820 * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
8821 * The selection of extraction is done standardly in new2old format.
8822 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8824 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8825 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8826 * \param [in] arrIn arr origin array from which the extraction will be done.
8827 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8828 * \param [out] arrOut the resulting array
8829 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8830 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8832 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8833 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8835 if(!arrIn || !arrIndxIn)
8836 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8837 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8838 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8840 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8841 const int *arrInPtr=arrIn->getConstPointer();
8842 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8843 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8845 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8846 int maxSizeOfArr=arrIn->getNumberOfTuples();
8847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8849 arrIo->alloc((int)(sz+1),1);
8850 int idsIt=idsOfSelectStart;
8851 int *work=arrIo->getPointer();
8854 for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8856 if(idsIt>=0 && idsIt<nbOfGrps)
8857 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8860 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8861 throw INTERP_KERNEL::Exception(oss.str().c_str());
8867 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8868 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8869 throw INTERP_KERNEL::Exception(oss.str().c_str());
8872 arro->alloc(lgth,1);
8873 work=arro->getPointer();
8874 idsIt=idsOfSelectStart;
8875 for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8877 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8878 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8881 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8882 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8883 throw INTERP_KERNEL::Exception(oss.str().c_str());
8887 arrIndexOut=arrIo.retn();
8891 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8892 * 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
8893 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8894 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8896 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8897 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8898 * \param [in] arrIn arr origin array from which the extraction will be done.
8899 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8900 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8901 * \param [in] srcArrIndex index array of \b srcArr
8902 * \param [out] arrOut the resulting array
8903 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8905 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8907 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8908 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8909 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8911 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8912 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8915 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8916 std::vector<bool> v(nbOfTuples,true);
8918 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8919 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8920 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8922 if(*it>=0 && *it<nbOfTuples)
8925 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8929 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8930 throw INTERP_KERNEL::Exception(oss.str().c_str());
8933 srcArrIndexPtr=srcArrIndex->getConstPointer();
8934 arrIo->alloc(nbOfTuples+1,1);
8935 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8936 const int *arrInPtr=arrIn->getConstPointer();
8937 const int *srcArrPtr=srcArr->getConstPointer();
8938 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8939 int *arroPtr=arro->getPointer();
8940 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8944 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8945 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8949 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8950 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8951 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8955 arrIndexOut=arrIo.retn();
8959 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8960 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8962 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8963 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8964 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8965 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8966 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8967 * \param [in] srcArrIndex index array of \b srcArr
8969 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8971 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8972 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8974 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8975 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8976 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8977 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8978 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8979 int *arrInOutPtr=arrInOut->getPointer();
8980 const int *srcArrPtr=srcArr->getConstPointer();
8981 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8983 if(*it>=0 && *it<nbOfTuples)
8985 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8986 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8989 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] !";
8990 throw INTERP_KERNEL::Exception(oss.str().c_str());
8995 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8996 throw INTERP_KERNEL::Exception(oss.str().c_str());
9002 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9003 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9004 * 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]].
9005 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9006 * A negative value in \b arrIn means that it is ignored.
9007 * 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.
9009 * \param [in] arrIn arr origin array from which the extraction will be done.
9010 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9011 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9012 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9014 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9016 int seed=0,nbOfDepthPeelingPerformed=0;
9017 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9021 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9022 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9023 * 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]].
9024 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9025 * A negative value in \b arrIn means that it is ignored.
9026 * 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.
9027 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9028 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9029 * \param [in] arrIn arr origin array from which the extraction will be done.
9030 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9031 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9032 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9033 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9034 * \sa MEDCouplingUMesh::partitionBySpreadZone
9036 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9038 nbOfDepthPeelingPerformed=0;
9040 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9041 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9044 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9048 std::vector<bool> fetched(nbOfTuples,false);
9049 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9052 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)
9054 nbOfDepthPeelingPerformed=0;
9055 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9056 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9057 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9058 std::vector<bool> fetched2(nbOfTuples,false);
9060 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9062 if(*seedElt>=0 && *seedElt<nbOfTuples)
9063 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9065 { 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()); }
9067 const int *arrInPtr=arrIn->getConstPointer();
9068 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9069 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9070 std::vector<int> idsToFetch1(seedBg,seedEnd);
9071 std::vector<int> idsToFetch2;
9072 std::vector<int> *idsToFetch=&idsToFetch1;
9073 std::vector<int> *idsToFetchOther=&idsToFetch2;
9074 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9076 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9077 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9079 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9080 std::swap(idsToFetch,idsToFetchOther);
9081 idsToFetchOther->clear();
9082 nbOfDepthPeelingPerformed++;
9084 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9086 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9087 int *retPtr=ret->getPointer();
9088 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9095 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9096 * 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
9097 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9098 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9100 * \param [in] start begin of set of ids of the input extraction (included)
9101 * \param [in] end end of set of ids of the input extraction (excluded)
9102 * \param [in] step step of the set of ids in range mode.
9103 * \param [in] arrIn arr origin array from which the extraction will be done.
9104 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9105 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9106 * \param [in] srcArrIndex index array of \b srcArr
9107 * \param [out] arrOut the resulting array
9108 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9110 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9112 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9113 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9114 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9116 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9117 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9118 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9120 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9122 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9123 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9124 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9126 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9128 if(it>=0 && it<nbOfTuples)
9129 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9132 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9133 throw INTERP_KERNEL::Exception(oss.str().c_str());
9136 srcArrIndexPtr=srcArrIndex->getConstPointer();
9137 arrIo->alloc(nbOfTuples+1,1);
9138 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9139 const int *arrInPtr=arrIn->getConstPointer();
9140 const int *srcArrPtr=srcArr->getConstPointer();
9141 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9142 int *arroPtr=arro->getPointer();
9143 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9145 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9148 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9149 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9153 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9154 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9158 arrIndexOut=arrIo.retn();
9162 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9163 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9165 * \param [in] start begin of set of ids of the input extraction (included)
9166 * \param [in] end end of set of ids of the input extraction (excluded)
9167 * \param [in] step step of the set of ids in range mode.
9168 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9169 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9170 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9171 * \param [in] srcArrIndex index array of \b srcArr
9173 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9175 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9176 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9178 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9179 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9180 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9181 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9182 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9183 int *arrInOutPtr=arrInOut->getPointer();
9184 const int *srcArrPtr=srcArr->getConstPointer();
9185 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9187 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9189 if(it>=0 && it<nbOfTuples)
9191 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9192 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9195 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9196 throw INTERP_KERNEL::Exception(oss.str().c_str());
9201 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9202 throw INTERP_KERNEL::Exception(oss.str().c_str());
9208 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9209 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9210 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9211 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9212 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9214 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9216 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9218 checkFullyDefined();
9219 int mdim=getMeshDimension();
9220 int spaceDim=getSpaceDimension();
9222 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9223 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9224 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9225 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9226 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9227 ret->setCoords(getCoords());
9228 ret->allocateCells((int)partition.size());
9230 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9232 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9233 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9237 cell=tmp->buildUnionOf2DMesh();
9240 cell=tmp->buildUnionOf3DMesh();
9243 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9246 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9249 ret->finishInsertingCells();
9254 * This method partitions \b this into contiguous zone.
9255 * This method only needs a well defined connectivity. Coordinates are not considered here.
9256 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9258 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9260 int nbOfCellsCur=getNumberOfCells();
9261 std::vector<DataArrayInt *> ret;
9264 DataArrayInt *neigh=0,*neighI=0;
9265 computeNeighborsOfCells(neigh,neighI);
9266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9267 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9268 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9270 while(seed<nbOfCellsCur)
9272 int nbOfPeelPerformed=0;
9273 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9274 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9276 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9277 ret.push_back((*it).retn());
9282 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9283 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9285 * \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.
9286 * \return a newly allocated DataArrayInt to be managed by the caller.
9287 * \throw In case of \a code has not the right format (typically of size 3*n)
9289 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9292 std::size_t nb=code.size()/3;
9293 if(code.size()%3!=0)
9294 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9295 ret->alloc((int)nb,2);
9296 int *retPtr=ret->getPointer();
9297 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9299 retPtr[0]=code[3*i+2];
9300 retPtr[1]=code[3*i+2]+code[3*i+1];
9306 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9307 * All cells in \a this are expected to be linear 3D cells.
9308 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9309 * It leads to an increase to number of cells.
9310 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9311 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9312 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9314 * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
9315 * For all other cells, the splitting policy will be ignored.
9316 * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added.
9317 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9318 * an id of old cell producing it. The caller is to delete this array using
9319 * decrRef() as it is no more needed.
9320 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9322 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9323 * \throw If \a this is not fully constituted with linear 3D cells.
9324 * \sa MEDCouplingUMesh::simplexize
9326 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
9328 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9329 checkConnectivityFullyDefined();
9330 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9331 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9332 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9333 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9335 int *retPt(ret->getPointer());
9336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9337 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9338 const int *oldc(_nodal_connec->begin());
9339 const int *oldci(_nodal_connec_index->begin());
9340 const double *coords(_coords->begin());
9341 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9343 std::vector<int> a; std::vector<double> b;
9344 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9345 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9346 const int *aa(&a[0]);
9349 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9351 *it=(-(*(it))-1+nbNodes);
9352 addPts->insertAtTheEnd(b.begin(),b.end());
9353 nbNodes+=(int)b.size()/3;
9355 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9356 newConn->insertAtTheEnd(aa,aa+4);
9358 if(!addPts->empty())
9360 addPts->rearrange(3);
9361 nbOfAdditionalPoints=addPts->getNumberOfTuples();
9362 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9363 ret0->setCoords(addPts);
9367 nbOfAdditionalPoints=0;
9368 ret0->setCoords(getCoords());
9370 ret0->setNodalConnectivity(newConn);
9372 ret->computeOffsets2();
9373 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9377 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9378 _own_cell(true),_cell_id(-1),_nb_cell(0)
9383 _nb_cell=mesh->getNumberOfCells();
9387 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9395 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9396 _own_cell(false),_cell_id(bg-1),
9403 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9406 if(_cell_id<_nb_cell)
9415 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9421 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9423 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9426 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9432 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9440 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9446 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9451 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9456 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9458 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9461 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9466 _nb_cell=mesh->getNumberOfCells();
9470 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9477 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9479 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9480 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9481 if(_cell_id<_nb_cell)
9483 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9484 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9485 int startId=_cell_id;
9486 _cell_id+=nbOfElems;
9487 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9493 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9497 _conn=mesh->getNodalConnectivity()->getPointer();
9498 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9502 void MEDCouplingUMeshCell::next()
9504 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9509 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9512 std::string MEDCouplingUMeshCell::repr() const
9514 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9516 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9518 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9522 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9525 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9527 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9528 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9530 return INTERP_KERNEL::NORM_ERROR;
9533 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9536 if(_conn_lgth!=NOTICABLE_FIRST_VAL)