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::getHeapMemorySize() const
122 ret+=_nodal_connec->getHeapMemorySize();
123 if(_nodal_connec_index)
124 ret+=_nodal_connec_index->getHeapMemorySize();
125 return MEDCouplingPointSet::getHeapMemorySize()+ret;
128 void MEDCouplingUMesh::updateTime() const
130 MEDCouplingPointSet::updateTime();
133 updateTimeWith(*_nodal_connec);
135 if(_nodal_connec_index)
137 updateTimeWith(*_nodal_connec_index);
141 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
146 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
147 * then \a this mesh is most probably is writable, exchangeable and available for most
148 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
149 * this method to check that all is in order with \a this mesh.
150 * \throw If the mesh dimension is not set.
151 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
152 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
153 * \throw If the connectivity data array has more than one component.
154 * \throw If the connectivity data array has a named component.
155 * \throw If the connectivity index data array has more than one component.
156 * \throw If the connectivity index data array has a named component.
158 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
161 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
163 MEDCouplingPointSet::checkCoherency();
164 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
166 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
168 std::ostringstream message;
169 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
170 throw INTERP_KERNEL::Exception(message.str().c_str());
175 if(_nodal_connec->getNumberOfComponents()!=1)
176 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
177 if(_nodal_connec->getInfoOnComponent(0)!="")
178 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
182 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
183 if(_nodal_connec_index)
185 if(_nodal_connec_index->getNumberOfComponents()!=1)
186 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
187 if(_nodal_connec_index->getInfoOnComponent(0)!="")
188 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
192 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
196 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
197 * then \a this mesh is most probably is writable, exchangeable and available for all
198 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
199 * method thoroughly checks the nodal connectivity.
200 * \param [in] eps - a not used parameter.
201 * \throw If the mesh dimension is not set.
202 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
203 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
204 * \throw If the connectivity data array has more than one component.
205 * \throw If the connectivity data array has a named component.
206 * \throw If the connectivity index data array has more than one component.
207 * \throw If the connectivity index data array has a named component.
208 * \throw If number of nodes defining an element does not correspond to the type of element.
209 * \throw If the nodal connectivity includes an invalid node id.
211 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
216 int meshDim=getMeshDimension();
217 int nbOfNodes=getNumberOfNodes();
218 int nbOfCells=getNumberOfCells();
219 const int *ptr=_nodal_connec->getConstPointer();
220 const int *ptrI=_nodal_connec_index->getConstPointer();
221 for(int i=0;i<nbOfCells;i++)
223 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
224 if((int)cm.getDimension()!=meshDim)
226 std::ostringstream oss;
227 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
228 throw INTERP_KERNEL::Exception(oss.str().c_str());
230 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
232 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
234 std::ostringstream oss;
235 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
236 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
237 throw INTERP_KERNEL::Exception(oss.str().c_str());
239 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
244 if(nodeId>=nbOfNodes)
246 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
247 throw INTERP_KERNEL::Exception(oss.str().c_str());
252 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
253 throw INTERP_KERNEL::Exception(oss.str().c_str());
257 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
259 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
260 throw INTERP_KERNEL::Exception(oss.str().c_str());
269 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
270 * then \a this mesh is most probably is writable, exchangeable and available for all
271 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
272 * \param [in] eps - a not used parameter.
273 * \throw If the mesh dimension is not set.
274 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
275 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
276 * \throw If the connectivity data array has more than one component.
277 * \throw If the connectivity data array has a named component.
278 * \throw If the connectivity index data array has more than one component.
279 * \throw If the connectivity index data array has a named component.
280 * \throw If number of nodes defining an element does not correspond to the type of element.
281 * \throw If the nodal connectivity includes an invalid node id.
283 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
285 checkCoherency1(eps);
289 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
290 * elements contained in the mesh. For more info on the mesh dimension see
291 * \ref MEDCouplingUMeshPage.
292 * \param [in] meshDim - a new mesh dimension.
293 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
295 void MEDCouplingUMesh::setMeshDimension(int meshDim)
297 if(meshDim<-1 || meshDim>3)
298 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
304 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
305 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
306 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
308 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
310 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
311 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
313 void MEDCouplingUMesh::allocateCells(int nbOfCells)
316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
317 if(_nodal_connec_index)
319 _nodal_connec_index->decrRef();
323 _nodal_connec->decrRef();
325 _nodal_connec_index=DataArrayInt::New();
326 _nodal_connec_index->reserve(nbOfCells+1);
327 _nodal_connec_index->pushBackSilent(0);
328 _nodal_connec=DataArrayInt::New();
329 _nodal_connec->reserve(2*nbOfCells);
335 * Appends a cell to the connectivity array. For deeper understanding what is
336 * happening see \ref MEDCouplingUMeshNodalConnectivity.
337 * \param [in] type - type of cell to add.
338 * \param [in] size - number of nodes constituting this cell.
339 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
341 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
342 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
344 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
346 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
347 if(_nodal_connec_index==0)
348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
349 if((int)cm.getDimension()==_mesh_dim)
352 if(size!=(int)cm.getNumberOfNodes())
354 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
355 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
356 throw INTERP_KERNEL::Exception(oss.str().c_str());
358 int idx=_nodal_connec_index->back();
360 _nodal_connec_index->pushBackSilent(val);
361 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
366 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
367 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
368 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
369 throw INTERP_KERNEL::Exception(oss.str().c_str());
374 * Compacts data arrays to release unused memory. This method is to be called after
375 * finishing cell insertion using \a this->insertNextCell().
377 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
378 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
380 void MEDCouplingUMesh::finishInsertingCells()
382 _nodal_connec->pack();
383 _nodal_connec_index->pack();
384 _nodal_connec->declareAsNew();
385 _nodal_connec_index->declareAsNew();
390 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
391 * Useful for python users.
393 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
395 return new MEDCouplingUMeshCellIterator(this);
399 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
400 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
401 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
402 * Useful for python users.
404 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
406 if(!checkConsecutiveCellTypes())
407 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
408 return new MEDCouplingUMeshCellByTypeEntry(this);
412 * Returns a set of all cell types available in \a this mesh.
413 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
414 * \warning this method does not throw any exception even if \a this is not defined.
416 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
422 * This method is a method that compares \a this and \a other.
423 * This method compares \b all attributes, even names and component names.
425 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
429 std::ostringstream oss; oss.precision(15);
430 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
433 reason="mesh given in input is not castable in MEDCouplingUMesh !";
436 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
438 if(_mesh_dim!=otherC->_mesh_dim)
440 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
444 if(_types!=otherC->_types)
446 oss << "umesh geometric type mismatch :\nThis geometric types are :";
447 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
448 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
449 oss << "\nOther geometric types are :";
450 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
451 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
455 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
456 if(_nodal_connec==0 || otherC->_nodal_connec==0)
458 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
461 if(_nodal_connec!=otherC->_nodal_connec)
462 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
464 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
467 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
468 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
470 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
473 if(_nodal_connec_index!=otherC->_nodal_connec_index)
474 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
476 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
483 * Checks if data arrays of this mesh (node coordinates, nodal
484 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
486 * \param [in] other - the mesh to compare with.
487 * \param [in] prec - precision value used to compare node coordinates.
488 * \return bool - \a true if the two meshes are same.
490 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
492 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
495 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
497 if(_mesh_dim!=otherC->_mesh_dim)
499 if(_types!=otherC->_types)
501 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
502 if(_nodal_connec==0 || otherC->_nodal_connec==0)
504 if(_nodal_connec!=otherC->_nodal_connec)
505 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
507 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
510 if(_nodal_connec_index!=otherC->_nodal_connec_index)
511 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
517 * Checks if \a this and \a other meshes are geometrically equivalent with high
518 * probability, else an exception is thrown. The meshes are considered equivalent if
519 * (1) meshes contain the same number of nodes and the same number of elements of the
520 * same types (2) three cells of the two meshes (first, last and middle) are based
521 * on coincident nodes (with a specified precision).
522 * \param [in] other - the mesh to compare with.
523 * \param [in] prec - the precision used to compare nodes of the two meshes.
524 * \throw If the two meshes do not match.
526 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
528 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
529 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
531 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
535 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
536 * cells each node belongs to.
537 * \warning For speed reasons, this method does not check if node ids in the nodal
538 * connectivity correspond to the size of node coordinates array.
539 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
540 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
541 * dividing cell ids in \a revNodal into groups each referring to one
542 * node. Its every element (except the last one) is an index pointing to the
543 * first id of a group of cells. For example cells sharing the node #1 are
544 * described by following range of indices:
545 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
546 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
547 * Number of cells sharing the *i*-th node is
548 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
549 * \throw If the coordinates array is not set.
550 * \throw If the nodal connectivity of cells is not defined.
552 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
553 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
555 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
558 int nbOfNodes=getNumberOfNodes();
559 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
560 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
561 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
562 const int *conn=_nodal_connec->getConstPointer();
563 const int *connIndex=_nodal_connec_index->getConstPointer();
564 int nbOfCells=getNumberOfCells();
565 int nbOfEltsInRevNodal=0;
566 for(int eltId=0;eltId<nbOfCells;eltId++)
568 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
569 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
570 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
571 if(*iter>=0)//for polyhedrons
573 nbOfEltsInRevNodal++;
574 revNodalIndxPtr[(*iter)+1]++;
577 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
578 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
579 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
580 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
581 for(int eltId=0;eltId<nbOfCells;eltId++)
583 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
584 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
585 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
586 if(*iter>=0)//for polyhedrons
587 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
593 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
598 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
604 if(cm.getOrientationStatus(nb,conn1,conn2))
611 class MinusOneSonsGenerator
614 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
615 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
616 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
617 static const int DELTA=1;
619 const INTERP_KERNEL::CellModel& _cm;
622 class MinusOneSonsGeneratorBiQuadratic
625 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
626 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
627 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
628 static const int DELTA=1;
630 const INTERP_KERNEL::CellModel& _cm;
633 class MinusTwoSonsGenerator
636 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
637 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
638 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
639 static const int DELTA=2;
641 const INTERP_KERNEL::CellModel& _cm;
647 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
648 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
649 * describing correspondence between cells of \a this and the result meshes are
650 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
651 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
652 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
653 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
654 * \warning For speed reasons, this method does not check if node ids in the nodal
655 * connectivity correspond to the size of node coordinates array.
656 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
657 * to write this mesh to the MED file, its cells must be sorted using
658 * sortCellsInMEDFileFrmt().
659 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
660 * each cell of \a this mesh.
661 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
662 * dividing cell ids in \a desc into groups each referring to one
663 * cell of \a this mesh. Its every element (except the last one) is an index
664 * pointing to the first id of a group of cells. For example cells of the
665 * result mesh bounding the cell #1 of \a this mesh are described by following
667 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
668 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
669 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
670 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
671 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
672 * by each cell of the result mesh.
673 * \param [in,out] revDescIndx - the array, of length one more than number of cells
674 * in the result mesh,
675 * dividing cell ids in \a revDesc into groups each referring to one
676 * cell of the result mesh the same way as \a descIndx divides \a desc.
677 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
678 * delete this mesh using decrRef() as it is no more needed.
679 * \throw If the coordinates array is not set.
680 * \throw If the nodal connectivity of cells is node defined.
681 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
682 * revDescIndx == NULL.
684 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
685 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
686 * \sa buildDescendingConnectivity2()
688 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
690 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
694 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
695 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
696 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
697 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
698 * \sa MEDCouplingUMesh::buildDescendingConnectivity
700 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
703 if(getMeshDimension()!=3)
704 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
705 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
709 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
710 * this->getMeshDimension(), that bound cells of \a this mesh. In
711 * addition arrays describing correspondence between cells of \a this and the result
712 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
713 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
714 * mesh. This method differs from buildDescendingConnectivity() in that apart
715 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
716 * result meshes. So a positive id means that order of nodes in corresponding cells
717 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
718 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
719 * i.e. cell ids are one-based.
720 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
721 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
722 * \warning For speed reasons, this method does not check if node ids in the nodal
723 * connectivity correspond to the size of node coordinates array.
724 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
725 * to write this mesh to the MED file, its cells must be sorted using
726 * sortCellsInMEDFileFrmt().
727 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
728 * each cell of \a this mesh.
729 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
730 * dividing cell ids in \a desc into groups each referring to one
731 * cell of \a this mesh. Its every element (except the last one) is an index
732 * pointing to the first id of a group of cells. For example cells of the
733 * result mesh bounding the cell #1 of \a this mesh are described by following
735 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
736 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
737 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
738 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
739 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
740 * by each cell of the result mesh.
741 * \param [in,out] revDescIndx - the array, of length one more than number of cells
742 * in the result mesh,
743 * dividing cell ids in \a revDesc into groups each referring to one
744 * cell of the result mesh the same way as \a descIndx divides \a desc.
745 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
746 * shares the node coordinates array with \a this mesh. The caller is to
747 * delete this mesh using decrRef() as it is no more needed.
748 * \throw If the coordinates array is not set.
749 * \throw If the nodal connectivity of cells is node defined.
750 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
751 * revDescIndx == NULL.
753 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
754 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
755 * \sa buildDescendingConnectivity()
757 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
759 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
763 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
764 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
765 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
766 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
768 * \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
769 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
770 * \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.
772 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
778 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
780 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
784 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
785 * 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,
786 * excluding a set of meshdim-1 cells in input descending connectivity.
787 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
788 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
789 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
791 * \param [in] desc descending connectivity array.
792 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
793 * \param [in] revDesc reverse descending connectivity array.
794 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
795 * \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
796 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
797 * \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.
799 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
800 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
802 if(!desc || !descIndx || !revDesc || !revDescIndx)
803 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
804 const int *descPtr=desc->getConstPointer();
805 const int *descIPtr=descIndx->getConstPointer();
806 const int *revDescPtr=revDesc->getConstPointer();
807 const int *revDescIPtr=revDescIndx->getConstPointer();
809 int nbCells=descIndx->getNumberOfTuples()-1;
810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
812 int *out1Ptr=out1->getPointer();
814 out0->reserve(desc->getNumberOfTuples());
815 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
817 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
819 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
821 out0->insertAtTheEnd(s.begin(),s.end());
823 *out1Ptr=out0->getNumberOfTuples();
825 neighbors=out0.retn();
826 neighborsIndx=out1.retn();
832 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
833 * For speed reasons no check of this will be done.
835 template<class SonsGenerator>
836 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
838 if(!desc || !descIndx || !revDesc || !revDescIndx)
839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
840 checkConnectivityFullyDefined();
841 int nbOfCells=getNumberOfCells();
842 int nbOfNodes=getNumberOfNodes();
843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
844 int *revNodalIndxPtr=revNodalIndx->getPointer();
845 const int *conn=_nodal_connec->getConstPointer();
846 const int *connIndex=_nodal_connec_index->getConstPointer();
847 std::string name="Mesh constituent of "; name+=getName();
848 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
849 ret->setCoords(getCoords());
850 ret->allocateCells(2*nbOfCells);
851 descIndx->alloc(nbOfCells+1,1);
852 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
853 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
854 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
856 int pos=connIndex[eltId];
857 int posP1=connIndex[eltId+1];
858 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
859 SonsGenerator sg(cm);
860 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
861 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
862 for(unsigned i=0;i<nbOfSons;i++)
864 INTERP_KERNEL::NormalizedCellType cmsId;
865 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
866 for(unsigned k=0;k<nbOfNodesSon;k++)
868 revNodalIndxPtr[tmp[k]+1]++;
869 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
870 revDesc2->pushBackSilent(eltId);
872 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
874 int nbOfCellsM1=ret->getNumberOfCells();
875 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
877 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
878 int *revNodalPtr=revNodal->getPointer();
879 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
880 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
881 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
883 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
884 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
885 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
886 if(*iter>=0)//for polyhedrons
887 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
890 DataArrayInt *commonCells=0,*commonCellsI=0;
891 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
893 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
894 int newNbOfCellsM1=-1;
895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
896 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
897 std::vector<bool> isImpacted(nbOfCellsM1,false);
898 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
899 for(int work2=work[0];work2!=work[1];work2++)
900 isImpacted[commonCellsPtr[work2]]=true;
901 const int *o2nM1Ptr=o2nM1->getConstPointer();
902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
903 const int *n2oM1Ptr=n2oM1->getConstPointer();
904 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
905 ret2->copyTinyInfoFrom(this);
906 desc->alloc(descIndx->back(),1);
907 int *descPtr=desc->getPointer();
908 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
909 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
912 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
915 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
917 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
918 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
921 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
924 revDesc->reserve(newNbOfCellsM1);
925 revDescIndx->alloc(newNbOfCellsM1+1,1);
926 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
927 const int *revDesc2Ptr=revDesc2->getConstPointer();
928 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
930 int oldCellIdM1=n2oM1Ptr[i];
931 if(!isImpacted[oldCellIdM1])
933 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
934 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
938 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
939 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
940 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
948 struct MEDCouplingAccVisit
950 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
951 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
952 int _new_nb_of_nodes;
958 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
959 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
960 * array of cell ids. Pay attention that after conversion all algorithms work slower
961 * with \a this mesh than before conversion. <br> If an exception is thrown during the
962 * conversion due presence of invalid ids in the array of cells to convert, as a
963 * result \a this mesh contains some already converted elements. In this case the 2D
964 * mesh remains valid but 3D mesh becomes \b inconsistent!
965 * \warning This method can significantly modify the order of geometric types in \a this,
966 * hence, to write this mesh to the MED file, its cells must be sorted using
967 * sortCellsInMEDFileFrmt().
968 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
969 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
970 * cellIdsToConvertBg.
971 * \throw If the coordinates array is not set.
972 * \throw If the nodal connectivity of cells is node defined.
973 * \throw If dimension of \a this mesh is not either 2 or 3.
975 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
976 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
978 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
981 int dim=getMeshDimension();
983 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
984 int nbOfCells=getNumberOfCells();
987 const int *connIndex=_nodal_connec_index->getConstPointer();
988 int *conn=_nodal_connec->getPointer();
989 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
991 if(*iter>=0 && *iter<nbOfCells)
993 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
994 if(!cm.isQuadratic())
995 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
997 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1001 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1002 oss << " in range [0," << nbOfCells << ") !";
1003 throw INTERP_KERNEL::Exception(oss.str().c_str());
1009 int *connIndex=_nodal_connec_index->getPointer();
1010 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1011 const int *connOld=_nodal_connec->getConstPointer();
1012 int connOldLgth=_nodal_connec->getNbOfElems();
1013 std::vector<int> connNew(connOld,connOld+connOldLgth);
1014 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1016 if(*iter>=0 && *iter<nbOfCells)
1018 int pos=connIndex[*iter];
1019 int posP1=connIndex[(*iter)+1];
1020 int lgthOld=posP1-pos-1;
1021 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1022 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1023 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1024 int *tmp=new int[nbOfFaces*lgthOld];
1026 for(int j=0;j<(int)nbOfFaces;j++)
1028 INTERP_KERNEL::NormalizedCellType type;
1029 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1033 std::size_t newLgth=std::distance(tmp,work)-1;
1034 std::size_t delta=newLgth-lgthOld;
1035 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1036 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1037 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1042 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1043 oss << " in range [0," << nbOfCells << ") !";
1044 throw INTERP_KERNEL::Exception(oss.str().c_str());
1047 _nodal_connec->alloc((int)connNew.size(),1);
1048 int *newConnPtr=_nodal_connec->getPointer();
1049 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1055 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1056 * polyhedrons (if \a this is a 3D mesh).
1057 * \warning As this method is purely for user-friendliness and no optimization is
1058 * done to avoid construction of a useless vector, this method can be costly
1060 * \throw If the coordinates array is not set.
1061 * \throw If the nodal connectivity of cells is node defined.
1062 * \throw If dimension of \a this mesh is not either 2 or 3.
1064 void MEDCouplingUMesh::convertAllToPoly()
1066 int nbOfCells=getNumberOfCells();
1067 std::vector<int> cellIds(nbOfCells);
1068 for(int i=0;i<nbOfCells;i++)
1070 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1074 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1075 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1076 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1077 * base facet of the volume and the second half of nodes describes an opposite facet
1078 * having the same number of nodes as the base one. This method converts such
1079 * connectivity to a valid polyhedral format where connectivity of each facet is
1080 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1081 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1082 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1083 * a correct orientation of the first facet of a polyhedron, else orientation of a
1084 * corrected cell is reverse.<br>
1085 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1086 * it releases the user from boring description of polyhedra connectivity in the valid
1088 * \throw If \a this->getMeshDimension() != 3.
1089 * \throw If \a this->getSpaceDimension() != 3.
1090 * \throw If the nodal connectivity of cells is not defined.
1091 * \throw If the coordinates array is not set.
1092 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1093 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1095 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1096 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1098 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1100 checkFullyDefined();
1101 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1102 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1103 int nbOfCells=getNumberOfCells();
1104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1105 newCi->alloc(nbOfCells+1,1);
1106 int *newci=newCi->getPointer();
1107 const int *ci=_nodal_connec_index->getConstPointer();
1108 const int *c=_nodal_connec->getConstPointer();
1110 for(int i=0;i<nbOfCells;i++)
1112 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1113 if(type==INTERP_KERNEL::NORM_POLYHED)
1115 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1117 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1118 throw INTERP_KERNEL::Exception(oss.str().c_str());
1120 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1123 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 !";
1124 throw INTERP_KERNEL::Exception(oss.str().c_str());
1127 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)
1130 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1133 newC->alloc(newci[nbOfCells],1);
1134 int *newc=newC->getPointer();
1135 for(int i=0;i<nbOfCells;i++)
1137 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1138 if(type==INTERP_KERNEL::NORM_POLYHED)
1140 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1141 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1143 for(std::size_t j=0;j<n1;j++)
1145 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1147 newc[n1+5*j+1]=c[ci[i]+1+j];
1148 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1149 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1150 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1155 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1157 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1158 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1163 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1164 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1165 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1166 * to write this mesh to the MED file, its cells must be sorted using
1167 * sortCellsInMEDFileFrmt().
1168 * \return \c true if at least one cell has been converted, \c false else. In the
1169 * last case the nodal connectivity remains unchanged.
1170 * \throw If the coordinates array is not set.
1171 * \throw If the nodal connectivity of cells is not defined.
1172 * \throw If \a this->getMeshDimension() < 0.
1174 bool MEDCouplingUMesh::unPolyze()
1176 checkFullyDefined();
1177 int mdim=getMeshDimension();
1179 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1182 int nbOfCells=getNumberOfCells();
1185 int initMeshLgth=getMeshLength();
1186 int *conn=_nodal_connec->getPointer();
1187 int *index=_nodal_connec_index->getPointer();
1192 for(int i=0;i<nbOfCells;i++)
1194 lgthOfCurCell=index[i+1]-posOfCurCell;
1195 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1196 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1197 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1201 switch(cm.getDimension())
1205 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1206 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1207 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1212 int nbOfFaces,lgthOfPolyhConn;
1213 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1214 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1219 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1223 ret=ret || (newType!=type);
1224 conn[newPos]=newType;
1226 posOfCurCell=index[i+1];
1231 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1232 newPos+=lgthOfCurCell;
1233 posOfCurCell+=lgthOfCurCell;
1237 if(newPos!=initMeshLgth)
1238 _nodal_connec->reAlloc(newPos);
1245 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1246 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1247 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1249 * \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
1252 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1254 checkFullyDefined();
1255 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1256 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1257 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1258 coords->recenterForMaxPrecision(eps);
1260 int nbOfCells=getNumberOfCells();
1261 const int *conn=_nodal_connec->getConstPointer();
1262 const int *index=_nodal_connec_index->getConstPointer();
1263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1264 connINew->alloc(nbOfCells+1,1);
1265 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1268 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1270 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1272 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1276 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1277 *connINewPtr=connNew->getNumberOfTuples();
1280 setConnectivity(connNew,connINew,false);
1284 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1285 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1286 * the format of returned DataArrayInt instance.
1288 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1289 * \sa MEDCouplingUMesh::getNodeIdsInUse
1291 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1293 checkConnectivityFullyDefined();
1294 int nbOfCells=getNumberOfCells();
1295 const int *connIndex=_nodal_connec_index->getConstPointer();
1296 const int *conn=_nodal_connec->getConstPointer();
1297 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1298 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1299 std::vector<bool> retS(maxElt,false);
1300 for(int i=0;i<nbOfCells;i++)
1301 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1305 for(int i=0;i<maxElt;i++)
1308 DataArrayInt *ret=DataArrayInt::New();
1310 int *retPtr=ret->getPointer();
1311 for(int i=0;i<maxElt;i++)
1318 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1319 * \sa MEDCouplingUMesh::getNodeIdsInUse
1321 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1323 int nbOfNodes=(int)nodeIdsInUse.size();
1324 int nbOfCells=getNumberOfCells();
1325 const int *connIndex=_nodal_connec_index->getConstPointer();
1326 const int *conn=_nodal_connec->getConstPointer();
1327 for(int i=0;i<nbOfCells;i++)
1328 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1331 if(conn[j]<nbOfNodes)
1332 nodeIdsInUse[conn[j]]=true;
1335 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1336 throw INTERP_KERNEL::Exception(oss.str().c_str());
1342 * Finds nodes not used in any cell and returns an array giving a new id to every node
1343 * by excluding the unused nodes, for which the array holds -1. The result array is
1344 * a mapping in "Old to New" mode.
1345 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1346 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1347 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1348 * if the node is unused or a new id else. The caller is to delete this
1349 * array using decrRef() as it is no more needed.
1350 * \throw If the coordinates array is not set.
1351 * \throw If the nodal connectivity of cells is not defined.
1352 * \throw If the nodal connectivity includes an invalid id.
1354 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1355 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1356 * \sa computeNodeIdsAlg()
1358 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1361 int nbOfNodes=getNumberOfNodes();
1362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1363 ret->alloc(nbOfNodes,1);
1364 int *traducer=ret->getPointer();
1365 std::fill(traducer,traducer+nbOfNodes,-1);
1366 int nbOfCells=getNumberOfCells();
1367 const int *connIndex=_nodal_connec_index->getConstPointer();
1368 const int *conn=_nodal_connec->getConstPointer();
1369 for(int i=0;i<nbOfCells;i++)
1370 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1373 if(conn[j]<nbOfNodes)
1374 traducer[conn[j]]=1;
1377 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1378 throw INTERP_KERNEL::Exception(oss.str().c_str());
1381 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1382 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1387 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1388 * For each cell in \b this the number of nodes constituting cell is computed.
1389 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1390 * So for pohyhedrons some nodes can be counted several times in the returned result.
1392 * \return a newly allocated array
1393 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1395 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1397 checkConnectivityFullyDefined();
1398 int nbOfCells=getNumberOfCells();
1399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1400 ret->alloc(nbOfCells,1);
1401 int *retPtr=ret->getPointer();
1402 const int *conn=getNodalConnectivity()->getConstPointer();
1403 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1404 for(int i=0;i<nbOfCells;i++,retPtr++)
1406 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1407 *retPtr=connI[i+1]-connI[i]-1;
1409 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1415 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1416 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1418 * \return DataArrayInt * - new object to be deallocated by the caller.
1419 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1421 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1423 checkConnectivityFullyDefined();
1424 int nbOfCells=getNumberOfCells();
1425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1426 ret->alloc(nbOfCells,1);
1427 int *retPtr=ret->getPointer();
1428 const int *conn=getNodalConnectivity()->getConstPointer();
1429 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1430 for(int i=0;i<nbOfCells;i++,retPtr++)
1432 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1433 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1434 *retPtr=(int)s.size();
1438 *retPtr=(int)s.size();
1445 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1446 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1448 * \return a newly allocated array
1450 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1452 checkConnectivityFullyDefined();
1453 int nbOfCells=getNumberOfCells();
1454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1455 ret->alloc(nbOfCells,1);
1456 int *retPtr=ret->getPointer();
1457 const int *conn=getNodalConnectivity()->getConstPointer();
1458 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1459 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1461 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1462 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1468 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1469 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1470 * array mean that the corresponding old node is no more used.
1471 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1472 * this->getNumberOfNodes() before call of this method. The caller is to
1473 * delete this array using decrRef() as it is no more needed.
1474 * \throw If the coordinates array is not set.
1475 * \throw If the nodal connectivity of cells is not defined.
1476 * \throw If the nodal connectivity includes an invalid id.
1478 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1479 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1481 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1483 return MEDCouplingPointSet::zipCoordsTraducer();
1487 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1488 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1490 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1495 return AreCellsEqual0(conn,connI,cell1,cell2);
1497 return AreCellsEqual1(conn,connI,cell1,cell2);
1499 return AreCellsEqual2(conn,connI,cell1,cell2);
1501 return AreCellsEqual3(conn,connI,cell1,cell2);
1503 return AreCellsEqual7(conn,connI,cell1,cell2);
1505 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1509 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1511 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1513 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1514 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1519 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1521 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1523 int sz=connI[cell1+1]-connI[cell1];
1524 if(sz==connI[cell2+1]-connI[cell2])
1526 if(conn[connI[cell1]]==conn[connI[cell2]])
1528 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1529 unsigned dim=cm.getDimension();
1535 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1536 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1537 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1538 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1539 return work!=tmp+sz1?1:0;
1542 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1545 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1552 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1554 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1556 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1558 if(conn[connI[cell1]]==conn[connI[cell2]])
1560 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1561 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1569 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1571 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1573 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1575 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1576 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1583 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1585 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1587 int sz=connI[cell1+1]-connI[cell1];
1588 if(sz==connI[cell2+1]-connI[cell2])
1590 if(conn[connI[cell1]]==conn[connI[cell2]])
1592 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1593 unsigned dim=cm.getDimension();
1599 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1600 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1601 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1602 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1607 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1608 std::reverse_iterator<int *> it2((int *)tmp);
1609 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1615 return work!=tmp+sz1?1:0;
1618 {//case of SEG2 and SEG3
1619 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1621 if(!cm.isQuadratic())
1623 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1624 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1625 if(std::equal(it1,it2,conn+connI[cell2]+1))
1631 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])
1638 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1645 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1646 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1647 * and result remains unchanged.
1648 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1649 * If in 'candidates' pool -1 value is considered as an empty value.
1650 * WARNING this method returns only ONE set of result !
1652 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1654 if(candidates.size()<1)
1657 std::vector<int>::const_iterator iter=candidates.begin();
1658 int start=(*iter++);
1659 for(;iter!=candidates.end();iter++)
1661 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1666 result->pushBackSilent(start);
1670 result->pushBackSilent(*iter);
1672 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1679 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1680 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1682 * \param [in] compType input specifying the technique used to compare cells each other.
1683 * - 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.
1684 * - 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)
1685 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1686 * - 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
1687 * can be used for users not sensitive to orientation of cell
1688 * \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.
1689 * \param [out] commonCells
1690 * \param [out] commonCellsI
1691 * \return the correspondance array old to new in a newly allocated array.
1694 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1696 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1697 getReverseNodalConnectivity(revNodal,revNodalI);
1698 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1701 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1702 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1705 int nbOfCells=nodalI->getNumberOfTuples()-1;
1706 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1707 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1708 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1709 std::vector<bool> isFetched(nbOfCells,false);
1712 for(int i=0;i<nbOfCells;i++)
1716 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1717 std::vector<int> v,v2;
1718 if(connOfNode!=connPtr+connIPtr[i+1])
1720 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1721 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1724 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1728 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1729 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1730 v2.resize(std::distance(v2.begin(),it));
1734 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1736 int pos=commonCellsI->back();
1737 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1738 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1739 isFetched[*it]=true;
1747 for(int i=startCellId;i<nbOfCells;i++)
1751 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1752 std::vector<int> v,v2;
1753 if(connOfNode!=connPtr+connIPtr[i+1])
1755 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1758 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1762 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1763 v2.resize(std::distance(v2.begin(),it));
1767 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1769 int pos=commonCellsI->back();
1770 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1771 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1772 isFetched[*it]=true;
1778 commonCellsArr=commonCells.retn();
1779 commonCellsIArr=commonCellsI.retn();
1783 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1784 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1785 * than \a other->getNumberOfCells() in the returned array means that there is no
1786 * corresponding cell in \a this mesh.
1787 * It is expected that \a this and \a other meshes share the same node coordinates
1788 * array, if it is not so an exception is thrown.
1789 * \param [in] other - the mesh to compare with.
1790 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1791 * valid values [0,1,2], see zipConnectivityTraducer().
1792 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1793 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1794 * values. The caller is to delete this array using
1795 * decrRef() as it is no more needed.
1796 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1799 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1800 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1801 * \sa checkDeepEquivalOnSameNodesWith()
1802 * \sa checkGeoEquivalWith()
1804 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1806 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1807 int nbOfCells=getNumberOfCells();
1808 static const int possibleCompType[]={0,1,2};
1809 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1811 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1812 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1814 throw INTERP_KERNEL::Exception(oss.str().c_str());
1816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1817 arr=o2n->substr(nbOfCells);
1818 arr->setName(other->getName().c_str());
1820 if(other->getNumberOfCells()==0)
1822 return arr->getMaxValue(tmp)<nbOfCells;
1826 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1827 * This method tries to determine if \b other is fully included in \b this.
1828 * The main difference is that this method is not expected to throw exception.
1829 * This method has two outputs :
1831 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1832 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1834 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1836 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1837 DataArrayInt *commonCells=0,*commonCellsI=0;
1838 int thisNbCells=getNumberOfCells();
1839 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1841 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1842 int otherNbCells=other->getNumberOfCells();
1843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1844 arr2->alloc(otherNbCells,1);
1845 arr2->fillWithZero();
1846 int *arr2Ptr=arr2->getPointer();
1847 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1848 for(int i=0;i<nbOfCommon;i++)
1850 int start=commonCellsPtr[commonCellsIPtr[i]];
1851 if(start<thisNbCells)
1853 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1855 int sig=commonCellsPtr[j]>0?1:-1;
1856 int val=std::abs(commonCellsPtr[j])-1;
1857 if(val>=thisNbCells)
1858 arr2Ptr[val-thisNbCells]=sig*(start+1);
1862 arr2->setName(other->getName().c_str());
1863 if(arr2->presenceOfValue(0))
1869 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1872 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1873 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1875 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1876 std::vector<const MEDCouplingUMesh *> ms(2);
1879 return MergeUMeshesOnSameCoords(ms);
1883 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1884 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1885 * cellIds is not given explicitely but by a range python like.
1887 * \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.
1888 * \return a newly allocated
1890 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1891 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1893 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1895 if(getMeshDimension()!=-1)
1896 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1899 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1901 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1903 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1905 return const_cast<MEDCouplingUMesh *>(this);
1910 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1911 * The result mesh shares or not the node coordinates array with \a this mesh depending
1912 * on \a keepCoords parameter.
1913 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1914 * to write this mesh to the MED file, its cells must be sorted using
1915 * sortCellsInMEDFileFrmt().
1916 * \param [in] begin - an array of cell ids to include to the new mesh.
1917 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1918 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1919 * array of \a this mesh, else "free" nodes are removed from the result mesh
1920 * by calling zipCoords().
1921 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1922 * to delete this mesh using decrRef() as it is no more needed.
1923 * \throw If the coordinates array is not set.
1924 * \throw If the nodal connectivity of cells is not defined.
1925 * \throw If any cell id in the array \a begin is not valid.
1927 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1928 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1930 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1932 if(getMeshDimension()!=-1)
1933 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1937 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1939 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1941 return const_cast<MEDCouplingUMesh *>(this);
1946 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1948 * 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.
1949 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1950 * The number of cells of \b this will remain the same with this method.
1952 * \param [in] begin begin of cell ids (included) of cells in this to assign
1953 * \param [in] end end of cell ids (excluded) of cells in this to assign
1954 * \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 ).
1955 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1957 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1959 checkConnectivityFullyDefined();
1960 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1961 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1962 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1963 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1965 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1966 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1967 throw INTERP_KERNEL::Exception(oss.str().c_str());
1969 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1970 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1972 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1973 throw INTERP_KERNEL::Exception(oss.str().c_str());
1975 int nbOfCells=getNumberOfCells();
1976 bool easyAssign=true;
1977 const int *connI=_nodal_connec_index->getConstPointer();
1978 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1979 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1981 if(*it>=0 && *it<nbOfCells)
1983 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1987 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1988 throw INTERP_KERNEL::Exception(oss.str().c_str());
1993 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1998 DataArrayInt *arrOut=0,*arrIOut=0;
1999 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2002 setConnectivity(arrOut,arrIOut,true);
2006 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2008 checkConnectivityFullyDefined();
2009 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2010 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2011 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2012 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2014 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2015 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2016 throw INTERP_KERNEL::Exception(oss.str().c_str());
2018 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2019 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2021 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2022 throw INTERP_KERNEL::Exception(oss.str().c_str());
2024 int nbOfCells=getNumberOfCells();
2025 bool easyAssign=true;
2026 const int *connI=_nodal_connec_index->getConstPointer();
2027 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2029 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2031 if(it>=0 && it<nbOfCells)
2033 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2037 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2038 throw INTERP_KERNEL::Exception(oss.str().c_str());
2043 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2048 DataArrayInt *arrOut=0,*arrIOut=0;
2049 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2051 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2052 setConnectivity(arrOut,arrIOut,true);
2057 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2058 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2059 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2060 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2062 * \param [in] begin input start of array of node ids.
2063 * \param [in] end input end of array of node ids.
2064 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2065 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2067 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2070 checkConnectivityFullyDefined();
2072 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2073 std::vector<bool> fastFinder(sz,false);
2074 for(const int *work=begin;work!=end;work++)
2075 if(*work>=0 && *work<sz)
2076 fastFinder[*work]=true;
2077 int nbOfCells=getNumberOfCells();
2078 const int *conn=getNodalConnectivity()->getConstPointer();
2079 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2080 for(int i=0;i<nbOfCells;i++)
2082 int ref=0,nbOfHit=0;
2083 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2087 if(fastFinder[*work2])
2090 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2091 cellIdsKept->pushBackSilent(i);
2093 cellIdsKeptArr=cellIdsKept.retn();
2097 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2098 * this->getMeshDimension(), that bound some cells of \a this mesh.
2099 * The cells of lower dimension to include to the result mesh are selected basing on
2100 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2101 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2102 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2103 * created mesh shares the node coordinates array with \a this mesh.
2104 * \param [in] begin - the array of node ids.
2105 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2106 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2107 * array \a begin are added, else cells whose any node is in the
2108 * array \a begin are added.
2109 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2110 * to delete this mesh using decrRef() as it is no more needed.
2111 * \throw If the coordinates array is not set.
2112 * \throw If the nodal connectivity of cells is not defined.
2113 * \throw If any node id in \a begin is not valid.
2115 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2116 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2118 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2120 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2121 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2122 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2123 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2124 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2128 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2129 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2130 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2131 * array of \a this mesh, else "free" nodes are removed from the result mesh
2132 * by calling zipCoords().
2133 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2134 * to delete this mesh using decrRef() as it is no more needed.
2135 * \throw If the coordinates array is not set.
2136 * \throw If the nodal connectivity of cells is not defined.
2138 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2139 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2141 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2143 DataArrayInt *desc=DataArrayInt::New();
2144 DataArrayInt *descIndx=DataArrayInt::New();
2145 DataArrayInt *revDesc=DataArrayInt::New();
2146 DataArrayInt *revDescIndx=DataArrayInt::New();
2148 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2151 descIndx->decrRef();
2152 int nbOfCells=meshDM1->getNumberOfCells();
2153 const int *revDescIndxC=revDescIndx->getConstPointer();
2154 std::vector<int> boundaryCells;
2155 for(int i=0;i<nbOfCells;i++)
2156 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2157 boundaryCells.push_back(i);
2158 revDescIndx->decrRef();
2159 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2164 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2165 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2166 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2168 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2170 checkFullyDefined();
2171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2176 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2177 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2181 const int *revDescPtr=revDesc->getConstPointer();
2182 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2183 int nbOfCells=getNumberOfCells();
2184 std::vector<bool> ret1(nbOfCells,false);
2186 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2187 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2188 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2190 DataArrayInt *ret2=DataArrayInt::New();
2192 int *ret2Ptr=ret2->getPointer();
2194 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2197 ret2->setName("BoundaryCells");
2202 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2203 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2204 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2205 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2207 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2208 * This method method returns cells ids set s = s1 + s2 where :
2210 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2211 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2213 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2214 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2216 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2217 * \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
2218 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2220 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2222 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2223 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2224 checkConnectivityFullyDefined();
2225 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2226 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2227 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2228 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2229 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2230 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2231 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2232 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2233 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2234 DataArrayInt *idsOtherInConsti=0;
2235 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2238 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2240 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2241 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2244 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2245 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2247 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2248 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2249 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2250 neighThisPartAuto=0;
2251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2252 const int li[2]={0,1};
2253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2254 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2258 cellIdsRk0=s0arr.retn();
2259 cellIdsRk1=s_renum1.retn();
2263 * 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
2264 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2266 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2268 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2275 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2276 revDesc=0; desc=0; descIndx=0;
2277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2279 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2283 * Finds nodes lying on the boundary of \a this mesh.
2284 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2285 * nodes. The caller is to delete this array using decrRef() as it is no
2287 * \throw If the coordinates array is not set.
2288 * \throw If the nodal connectivity of cells is node defined.
2290 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2291 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2293 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2296 return skin->computeFetchedNodeIds();
2299 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2302 return const_cast<MEDCouplingUMesh *>(this);
2306 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2307 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2308 * 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.
2309 * 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.
2310 * 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.
2312 * \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
2313 * parameter is altered during the call.
2314 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2315 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2316 * \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.
2318 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2320 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2321 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2323 checkFullyDefined();
2324 otherDimM1OnSameCoords.checkFullyDefined();
2325 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2326 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2327 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2328 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2329 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2330 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2333 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2334 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2338 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2340 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2342 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2343 DataArrayInt *idsTmp=0;
2344 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2347 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2348 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2349 DataArrayInt *tmp0=0,*tmp1=0;
2350 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2355 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2356 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2358 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2359 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2360 nodeIdsToDuplicate=s3.retn();
2364 * This method operates a modification of the connectivity and coords in \b this.
2365 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2366 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2367 * 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
2368 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2369 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2371 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2373 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2374 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2376 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2378 int nbOfNodes=getNumberOfNodes();
2379 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2380 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2384 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2385 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2386 * This method is a generalization of shiftNodeNumbersInConn().
2387 * \warning This method performs no check of validity of new ids. **Use it with care !**
2388 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2389 * this->getNumberOfNodes(), in "Old to New" mode.
2390 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2391 * \throw If the nodal connectivity of cells is not defined.
2393 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2394 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2396 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2398 checkConnectivityFullyDefined();
2399 int *conn=getNodalConnectivity()->getPointer();
2400 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2401 int nbOfCells=getNumberOfCells();
2402 for(int i=0;i<nbOfCells;i++)
2403 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2405 int& node=conn[iconn];
2406 if(node>=0)//avoid polyhedron separator
2408 node=newNodeNumbersO2N[node];
2411 _nodal_connec->declareAsNew();
2416 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2417 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2418 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2420 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2422 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2424 checkConnectivityFullyDefined();
2425 int *conn=getNodalConnectivity()->getPointer();
2426 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2427 int nbOfCells=getNumberOfCells();
2428 for(int i=0;i<nbOfCells;i++)
2429 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2431 int& node=conn[iconn];
2432 if(node>=0)//avoid polyhedron separator
2437 _nodal_connec->declareAsNew();
2442 * This method operates a modification of the connectivity in \b this.
2443 * 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.
2444 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2445 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2446 * 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
2447 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2448 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2450 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2451 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2453 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2454 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2455 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2457 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2459 checkConnectivityFullyDefined();
2460 std::map<int,int> m;
2462 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2464 int *conn=getNodalConnectivity()->getPointer();
2465 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2466 int nbOfCells=getNumberOfCells();
2467 for(int i=0;i<nbOfCells;i++)
2468 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2470 int& node=conn[iconn];
2471 if(node>=0)//avoid polyhedron separator
2473 std::map<int,int>::iterator it=m.find(node);
2482 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2484 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2485 * After the call of this method the number of cells remains the same as before.
2487 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2488 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2489 * be strictly in [0;this->getNumberOfCells()).
2491 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2492 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2493 * should be contained in[0;this->getNumberOfCells()).
2495 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2497 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2499 checkConnectivityFullyDefined();
2500 int nbCells=getNumberOfCells();
2501 const int *array=old2NewBg;
2503 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2505 const int *conn=_nodal_connec->getConstPointer();
2506 const int *connI=_nodal_connec_index->getConstPointer();
2507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2509 const int *n2oPtr=n2o->begin();
2510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2511 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2512 newConn->copyStringInfoFrom(*_nodal_connec);
2513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2514 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2515 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2517 int *newC=newConn->getPointer();
2518 int *newCI=newConnI->getPointer();
2521 for(int i=0;i<nbCells;i++)
2524 int nbOfElts=connI[pos+1]-connI[pos];
2525 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2530 setConnectivity(newConn,newConnI);
2532 free(const_cast<int *>(array));
2536 * Finds cells whose bounding boxes intersect a given bounding box.
2537 * \param [in] bbox - an array defining the bounding box via coordinates of its
2538 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2540 * \param [in] eps - a factor used to increase size of the bounding box of cell
2541 * before comparing it with \a bbox. This factor is multiplied by the maximal
2542 * extent of the bounding box of cell to produce an addition to this bounding box.
2543 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2544 * cells. The caller is to delete this array using decrRef() as it is no more
2546 * \throw If the coordinates array is not set.
2547 * \throw If the nodal connectivity of cells is not defined.
2549 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2550 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2552 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2554 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2555 if(getMeshDimension()==-1)
2557 elems->pushBackSilent(0);
2558 return elems.retn();
2560 int dim=getSpaceDimension();
2561 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2562 const int* conn = getNodalConnectivity()->getConstPointer();
2563 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2564 const double* coords = getCoords()->getConstPointer();
2565 int nbOfCells=getNumberOfCells();
2566 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2568 for (int i=0; i<dim; i++)
2570 elem_bb[i*2]=std::numeric_limits<double>::max();
2571 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2574 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2576 int node= conn[inode];
2577 if(node>=0)//avoid polyhedron separator
2579 for (int idim=0; idim<dim; idim++)
2581 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2583 elem_bb[idim*2] = coords[node*dim+idim] ;
2585 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2587 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2592 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2593 elems->pushBackSilent(ielem);
2595 return elems.retn();
2599 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2600 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2601 * added in 'elems' parameter.
2603 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2606 if(getMeshDimension()==-1)
2608 elems->pushBackSilent(0);
2609 return elems.retn();
2611 int dim=getSpaceDimension();
2612 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2613 const int* conn = getNodalConnectivity()->getConstPointer();
2614 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2615 const double* coords = getCoords()->getConstPointer();
2616 int nbOfCells=getNumberOfCells();
2617 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2619 for (int i=0; i<dim; i++)
2621 elem_bb[i*2]=std::numeric_limits<double>::max();
2622 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2625 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2627 int node= conn[inode];
2628 if(node>=0)//avoid polyhedron separator
2630 for (int idim=0; idim<dim; idim++)
2632 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2634 elem_bb[idim*2] = coords[node*dim+idim] ;
2636 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2638 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2643 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2644 elems->pushBackSilent(ielem);
2646 return elems.retn();
2650 * Returns a type of a cell by its id.
2651 * \param [in] cellId - the id of the cell of interest.
2652 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2653 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2655 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2657 const int *ptI=_nodal_connec_index->getConstPointer();
2658 const int *pt=_nodal_connec->getConstPointer();
2659 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2660 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2663 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2664 throw INTERP_KERNEL::Exception(oss.str().c_str());
2669 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2670 * This method does not throw exception if geometric type \a type is not in \a this.
2671 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2672 * The coordinates array is not considered here.
2674 * \param [in] type the geometric type
2675 * \return cell ids in this having geometric type \a type.
2677 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2680 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2682 checkConnectivityFullyDefined();
2683 int nbCells=getNumberOfCells();
2684 int mdim=getMeshDimension();
2685 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2686 if(mdim!=(int)cm.getDimension())
2687 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2688 const int *ptI=_nodal_connec_index->getConstPointer();
2689 const int *pt=_nodal_connec->getConstPointer();
2690 for(int i=0;i<nbCells;i++)
2692 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2693 ret->pushBackSilent(i);
2699 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2701 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2703 const int *ptI=_nodal_connec_index->getConstPointer();
2704 const int *pt=_nodal_connec->getConstPointer();
2705 int nbOfCells=getNumberOfCells();
2707 for(int i=0;i<nbOfCells;i++)
2708 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2714 * Returns the nodal connectivity of a given cell.
2715 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2716 * all returned node ids can be used in getCoordinatesOfNode().
2717 * \param [in] cellId - an id of the cell of interest.
2718 * \param [in,out] conn - a vector where the node ids are appended. It is not
2719 * cleared before the appending.
2720 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2722 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2724 const int *ptI=_nodal_connec_index->getConstPointer();
2725 const int *pt=_nodal_connec->getConstPointer();
2726 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2731 std::string MEDCouplingUMesh::simpleRepr() const
2733 static const char msg0[]="No coordinates specified !";
2734 std::ostringstream ret;
2735 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2736 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2738 double tt=getTime(tmpp1,tmpp2);
2739 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2740 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2742 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2744 { ret << " Mesh dimension has not been set or is invalid !"; }
2747 const int spaceDim=getSpaceDimension();
2748 ret << spaceDim << "\nInfo attached on space dimension : ";
2749 for(int i=0;i<spaceDim;i++)
2750 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2754 ret << msg0 << "\n";
2755 ret << "Number of nodes : ";
2757 ret << getNumberOfNodes() << "\n";
2759 ret << msg0 << "\n";
2760 ret << "Number of cells : ";
2761 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2762 ret << getNumberOfCells() << "\n";
2764 ret << "No connectivity specified !" << "\n";
2765 ret << "Cell types present : ";
2766 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2768 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2769 ret << cm.getRepr() << " ";
2775 std::string MEDCouplingUMesh::advancedRepr() const
2777 std::ostringstream ret;
2778 ret << simpleRepr();
2779 ret << "\nCoordinates array : \n___________________\n\n";
2781 _coords->reprWithoutNameStream(ret);
2783 ret << "No array set !\n";
2784 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2785 reprConnectivityOfThisLL(ret);
2790 * This method returns a C++ code that is a dump of \a this.
2791 * This method will throw if this is not fully defined.
2793 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2795 static const char coordsName[]="coords";
2796 static const char connName[]="conn";
2797 static const char connIName[]="connI";
2798 checkFullyDefined();
2799 std::ostringstream ret; ret << "// coordinates" << std::endl;
2800 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2801 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2802 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2803 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2804 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2805 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2806 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2810 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2812 std::ostringstream ret;
2813 reprConnectivityOfThisLL(ret);
2818 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2819 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2820 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2823 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2824 * 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
2825 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2827 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2829 int mdim=getMeshDimension();
2831 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2832 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2834 bool needToCpyCT=true;
2837 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2845 if(!_nodal_connec_index)
2847 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2852 tmp2=_nodal_connec_index;
2855 ret->setConnectivity(tmp1,tmp2,false);
2860 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2861 ret->setCoords(coords);
2864 ret->setCoords(_coords);
2868 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2870 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2872 int nbOfCells=getNumberOfCells();
2873 const int *c=_nodal_connec->getConstPointer();
2874 const int *ci=_nodal_connec_index->getConstPointer();
2875 for(int i=0;i<nbOfCells;i++)
2877 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2878 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2879 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2884 stream << "Connectivity not defined !\n";
2887 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2889 const int *ptI=_nodal_connec_index->getConstPointer();
2890 const int *pt=_nodal_connec->getConstPointer();
2891 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2892 return ptI[cellId+1]-ptI[cellId]-1;
2894 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2898 * Returns types of cells of the specified part of \a this mesh.
2899 * This method avoids computing sub-mesh explicitely to get its types.
2900 * \param [in] begin - an array of cell ids of interest.
2901 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2902 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2903 * describing the cell types.
2904 * \throw If the coordinates array is not set.
2905 * \throw If the nodal connectivity of cells is not defined.
2908 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2910 checkFullyDefined();
2911 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2912 const int *conn=_nodal_connec->getConstPointer();
2913 const int *connIndex=_nodal_connec_index->getConstPointer();
2914 for(const int *w=begin;w!=end;w++)
2915 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2920 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2921 * a set of types of cells constituting \a this mesh.
2922 * This method is for advanced users having prepared their connectivity before. For
2923 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2924 * \param [in] conn - the nodal connectivity array.
2925 * \param [in] connIndex - the nodal connectivity index array.
2926 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2929 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2931 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2932 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2933 if(isComputingTypes)
2939 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2940 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2942 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2943 _nodal_connec(0),_nodal_connec_index(0),
2944 _types(other._types)
2946 if(other._nodal_connec)
2947 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2948 if(other._nodal_connec_index)
2949 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2952 MEDCouplingUMesh::~MEDCouplingUMesh()
2955 _nodal_connec->decrRef();
2956 if(_nodal_connec_index)
2957 _nodal_connec_index->decrRef();
2961 * Recomputes a set of cell types of \a this mesh. For more info see
2962 * \ref MEDCouplingUMeshNodalConnectivity.
2964 void MEDCouplingUMesh::computeTypes()
2966 if(_nodal_connec && _nodal_connec_index)
2969 const int *conn=_nodal_connec->getConstPointer();
2970 const int *connIndex=_nodal_connec_index->getConstPointer();
2971 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2973 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2974 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2979 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2981 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2983 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2984 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2988 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2990 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2992 if(!_nodal_connec_index || !_nodal_connec)
2993 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2997 * Returns a number of cells constituting \a this mesh.
2998 * \return int - the number of cells in \a this mesh.
2999 * \throw If the nodal connectivity of cells is not defined.
3001 int MEDCouplingUMesh::getNumberOfCells() const
3003 if(_nodal_connec_index)
3004 return _nodal_connec_index->getNumberOfTuples()-1;
3009 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3013 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3014 * mesh. For more info see \ref MEDCouplingMeshesPage.
3015 * \return int - the dimension of \a this mesh.
3016 * \throw If the mesh dimension is not defined using setMeshDimension().
3018 int MEDCouplingUMesh::getMeshDimension() const
3021 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3026 * Returns a length of the nodal connectivity array.
3027 * This method is for test reason. Normally the integer returned is not useable by
3028 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3029 * \return int - the length of the nodal connectivity array.
3031 int MEDCouplingUMesh::getMeshLength() const
3033 return _nodal_connec->getNbOfElems();
3037 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3039 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3041 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3042 tinyInfo.push_back(getMeshDimension());
3043 tinyInfo.push_back(getNumberOfCells());
3045 tinyInfo.push_back(getMeshLength());
3047 tinyInfo.push_back(-1);
3051 * First step of unserialization process.
3053 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3055 return tinyInfo[6]<=0;
3059 * Second step of serialization process.
3060 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3062 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3064 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3066 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3070 * Third and final step of serialization process.
3072 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3074 MEDCouplingPointSet::serialize(a1,a2);
3075 if(getMeshDimension()>-1)
3077 a1=DataArrayInt::New();
3078 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3079 int *ptA1=a1->getPointer();
3080 const int *conn=getNodalConnectivity()->getConstPointer();
3081 const int *index=getNodalConnectivityIndex()->getConstPointer();
3082 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3083 std::copy(conn,conn+getMeshLength(),ptA1);
3090 * Second and final unserialization process.
3091 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3093 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3095 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3096 setMeshDimension(tinyInfo[5]);
3100 const int *recvBuffer=a1->getConstPointer();
3101 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3102 myConnecIndex->alloc(tinyInfo[6]+1,1);
3103 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3105 myConnec->alloc(tinyInfo[7],1);
3106 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3107 setConnectivity(myConnec, myConnecIndex);
3112 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3113 * CellIds are given using range specified by a start an end and step.
3115 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3117 checkFullyDefined();
3118 int ncell=getNumberOfCells();
3119 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3120 ret->_mesh_dim=_mesh_dim;
3121 ret->setCoords(_coords);
3122 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3124 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3126 const int *conn=_nodal_connec->getConstPointer();
3127 const int *connIndex=_nodal_connec_index->getConstPointer();
3128 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3130 if(work>=0 && work<ncell)
3132 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3136 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3137 throw INTERP_KERNEL::Exception(oss.str().c_str());
3140 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3141 int *newConnPtr=newConn->getPointer();
3142 std::set<INTERP_KERNEL::NormalizedCellType> types;
3144 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3146 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3147 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3149 ret->setConnectivity(newConn,newConnI,false);
3151 ret->copyTinyInfoFrom(this);
3156 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3157 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3158 * The return newly allocated mesh will share the same coordinates as \a this.
3160 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3162 checkConnectivityFullyDefined();
3163 int ncell=getNumberOfCells();
3164 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3165 ret->_mesh_dim=_mesh_dim;
3166 ret->setCoords(_coords);
3167 std::size_t nbOfElemsRet=std::distance(begin,end);
3168 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3170 const int *conn=_nodal_connec->getConstPointer();
3171 const int *connIndex=_nodal_connec_index->getConstPointer();
3173 for(const int *work=begin;work!=end;work++,newNbring++)
3175 if(*work>=0 && *work<ncell)
3176 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3180 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3181 throw INTERP_KERNEL::Exception(oss.str().c_str());
3184 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3185 int *connRetWork=connRet;
3186 std::set<INTERP_KERNEL::NormalizedCellType> types;
3187 for(const int *work=begin;work!=end;work++)
3189 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3190 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3192 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3193 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3195 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3196 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3198 ret->copyTinyInfoFrom(this);
3203 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3205 * For 1D cells, the returned field contains lengths.<br>
3206 * For 2D cells, the returned field contains areas.<br>
3207 * For 3D cells, the returned field contains volumes.
3208 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3209 * orientation, i.e. the volume is always positive.
3210 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3211 * and one time . The caller is to delete this field using decrRef() as it is no
3214 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3216 std::string name="MeasureOfMesh_";
3218 int nbelem=getNumberOfCells();
3219 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3220 field->setName(name.c_str());
3221 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3222 array->alloc(nbelem,1);
3223 double *area_vol=array->getPointer();
3224 field->setArray(array) ; array=0;
3225 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3226 field->synchronizeTimeWithMesh();
3227 if(getMeshDimension()!=-1)
3230 INTERP_KERNEL::NormalizedCellType type;
3231 int dim_space=getSpaceDimension();
3232 const double *coords=getCoords()->getConstPointer();
3233 const int *connec=getNodalConnectivity()->getConstPointer();
3234 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3235 for(int iel=0;iel<nbelem;iel++)
3237 ipt=connec_index[iel];
3238 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3239 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);
3242 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3246 area_vol[0]=std::numeric_limits<double>::max();
3248 return field.retn();
3252 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3254 * For 1D cells, the returned array contains lengths.<br>
3255 * For 2D cells, the returned array contains areas.<br>
3256 * For 3D cells, the returned array contains volumes.
3257 * This method avoids building explicitly a part of \a this mesh to perform the work.
3258 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3259 * orientation, i.e. the volume is always positive.
3260 * \param [in] begin - an array of cell ids of interest.
3261 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3262 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3263 * delete this array using decrRef() as it is no more needed.
3265 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3266 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3267 * \sa getMeasureField()
3269 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3271 std::string name="PartMeasureOfMesh_";
3273 int nbelem=(int)std::distance(begin,end);
3274 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3275 array->setName(name.c_str());
3276 array->alloc(nbelem,1);
3277 double *area_vol=array->getPointer();
3278 if(getMeshDimension()!=-1)
3281 INTERP_KERNEL::NormalizedCellType type;
3282 int dim_space=getSpaceDimension();
3283 const double *coords=getCoords()->getConstPointer();
3284 const int *connec=getNodalConnectivity()->getConstPointer();
3285 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3286 for(const int *iel=begin;iel!=end;iel++)
3288 ipt=connec_index[*iel];
3289 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3290 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3293 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3297 area_vol[0]=std::numeric_limits<double>::max();
3299 return array.retn();
3303 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3304 * \a this one. The returned field contains the dual cell volume for each corresponding
3305 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3306 * the dual mesh in P1 sens of \a this.<br>
3307 * For 1D cells, the returned field contains lengths.<br>
3308 * For 2D cells, the returned field contains areas.<br>
3309 * For 3D cells, the returned field contains volumes.
3310 * This method is useful to check "P1*" conservative interpolators.
3311 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3312 * orientation, i.e. the volume is always positive.
3313 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3314 * nodes and one time. The caller is to delete this array using decrRef() as
3315 * it is no more needed.
3317 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3319 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3320 std::string name="MeasureOnNodeOfMesh_";
3322 int nbNodes=getNumberOfNodes();
3323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3324 double cst=1./((double)getMeshDimension()+1.);
3325 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3326 array->alloc(nbNodes,1);
3327 double *valsToFill=array->getPointer();
3328 std::fill(valsToFill,valsToFill+nbNodes,0.);
3329 const double *values=tmp->getArray()->getConstPointer();
3330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3332 getReverseNodalConnectivity(da,daInd);
3333 const int *daPtr=da->getConstPointer();
3334 const int *daIPtr=daInd->getConstPointer();
3335 for(int i=0;i<nbNodes;i++)
3336 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3337 valsToFill[i]+=cst*values[*cell];
3339 ret->setArray(array);
3344 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3345 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3346 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3347 * and are normalized.
3348 * <br> \a this can be either
3349 * - a 2D mesh in 2D or 3D space or
3350 * - an 1D mesh in 2D space.
3352 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3353 * cells and one time. The caller is to delete this field using decrRef() as
3354 * it is no more needed.
3355 * \throw If the nodal connectivity of cells is not defined.
3356 * \throw If the coordinates array is not set.
3357 * \throw If the mesh dimension is not set.
3358 * \throw If the mesh and space dimension is not as specified above.
3360 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3362 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3363 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3364 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3365 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3366 int nbOfCells=getNumberOfCells();
3367 int nbComp=getMeshDimension()+1;
3368 array->alloc(nbOfCells,nbComp);
3369 double *vals=array->getPointer();
3370 const int *connI=_nodal_connec_index->getConstPointer();
3371 const int *conn=_nodal_connec->getConstPointer();
3372 const double *coords=_coords->getConstPointer();
3373 if(getMeshDimension()==2)
3375 if(getSpaceDimension()==3)
3377 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3378 const double *locPtr=loc->getConstPointer();
3379 for(int i=0;i<nbOfCells;i++,vals+=3)
3381 int offset=connI[i];
3382 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3383 double n=INTERP_KERNEL::norm<3>(vals);
3384 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3389 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3390 const double *isAbsPtr=isAbs->getArray()->begin();
3391 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3392 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3395 else//meshdimension==1
3398 for(int i=0;i<nbOfCells;i++)
3400 int offset=connI[i];
3401 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3402 double n=INTERP_KERNEL::norm<2>(tmp);
3403 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3408 ret->setArray(array);
3410 ret->synchronizeTimeWithSupport();
3415 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3416 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3417 * and are normalized.
3418 * <br> \a this can be either
3419 * - a 2D mesh in 2D or 3D space or
3420 * - an 1D mesh in 2D space.
3422 * This method avoids building explicitly a part of \a this mesh to perform the work.
3423 * \param [in] begin - an array of cell ids of interest.
3424 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3425 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3426 * cells and one time. The caller is to delete this field using decrRef() as
3427 * it is no more needed.
3428 * \throw If the nodal connectivity of cells is not defined.
3429 * \throw If the coordinates array is not set.
3430 * \throw If the mesh dimension is not set.
3431 * \throw If the mesh and space dimension is not as specified above.
3432 * \sa buildOrthogonalField()
3434 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3435 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3437 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3439 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3440 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3441 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3442 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3443 std::size_t nbelems=std::distance(begin,end);
3444 int nbComp=getMeshDimension()+1;
3445 array->alloc((int)nbelems,nbComp);
3446 double *vals=array->getPointer();
3447 const int *connI=_nodal_connec_index->getConstPointer();
3448 const int *conn=_nodal_connec->getConstPointer();
3449 const double *coords=_coords->getConstPointer();
3450 if(getMeshDimension()==2)
3452 if(getSpaceDimension()==3)
3454 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3455 const double *locPtr=loc->getConstPointer();
3456 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3458 int offset=connI[*i];
3459 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3460 double n=INTERP_KERNEL::norm<3>(vals);
3461 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3466 for(std::size_t i=0;i<nbelems;i++)
3467 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3470 else//meshdimension==1
3473 for(const int *i=begin;i!=end;i++)
3475 int offset=connI[*i];
3476 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3477 double n=INTERP_KERNEL::norm<2>(tmp);
3478 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3483 ret->setArray(array);
3485 ret->synchronizeTimeWithSupport();
3490 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3491 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3492 * and are \b not normalized.
3493 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3494 * cells and one time. The caller is to delete this field using decrRef() as
3495 * it is no more needed.
3496 * \throw If the nodal connectivity of cells is not defined.
3497 * \throw If the coordinates array is not set.
3498 * \throw If \a this->getMeshDimension() != 1.
3499 * \throw If \a this mesh includes cells of type other than SEG2.
3501 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3503 if(getMeshDimension()!=1)
3504 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3505 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3506 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3507 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3508 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3509 int nbOfCells=getNumberOfCells();
3510 int spaceDim=getSpaceDimension();
3511 array->alloc(nbOfCells,spaceDim);
3512 double *pt=array->getPointer();
3513 const double *coo=getCoords()->getConstPointer();
3514 std::vector<int> conn;
3516 for(int i=0;i<nbOfCells;i++)
3519 getNodeIdsOfCell(i,conn);
3520 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3522 ret->setArray(array);
3524 ret->synchronizeTimeWithSupport();
3529 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3530 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3531 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3532 * from. If a result face is shared by two 3D cells, then the face in included twice in
3534 * \param [in] origin - 3 components of a point defining location of the plane.
3535 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3536 * must be greater than 1e-6.
3537 * \param [in] eps - half-thickness of the plane.
3538 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3539 * producing correspondent 2D cells. The caller is to delete this array
3540 * using decrRef() as it is no more needed.
3541 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3542 * not share the node coordinates array with \a this mesh. The caller is to
3543 * delete this mesh using decrRef() as it is no more needed.
3544 * \throw If the coordinates array is not set.
3545 * \throw If the nodal connectivity of cells is not defined.
3546 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3547 * \throw If magnitude of \a vec is less than 1e-6.
3548 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3549 * \throw If \a this includes quadratic cells.
3551 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3553 checkFullyDefined();
3554 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3555 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3556 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3557 if(candidates->empty())
3558 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3559 std::vector<int> nodes;
3560 DataArrayInt *cellIds1D=0;
3561 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3562 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3563 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3565 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3567 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3568 revDesc2=0; revDescIndx2=0;
3569 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3570 revDesc1=0; revDescIndx1=0;
3571 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3572 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3574 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3575 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3577 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3578 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3579 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3580 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3581 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3582 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3583 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3584 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3585 if(cellIds2->empty())
3586 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3587 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3588 ret->setCoords(mDesc1->getCoords());
3589 ret->setConnectivity(conn,connI,true);
3590 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3595 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3596 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
3597 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3599 * \param [in] origin - 3 components of a point defining location of the plane.
3600 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3601 * must be greater than 1e-6.
3602 * \param [in] eps - half-thickness of the plane.
3603 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3604 * producing correspondent segments. The caller is to delete this array
3605 * using decrRef() as it is no more needed.
3606 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3607 * mesh in 3D space. This mesh does not share the node coordinates array with
3608 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3610 * \throw If the coordinates array is not set.
3611 * \throw If the nodal connectivity of cells is not defined.
3612 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3613 * \throw If magnitude of \a vec is less than 1e-6.
3614 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3615 * \throw If \a this includes quadratic cells.
3617 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3619 checkFullyDefined();
3620 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3622 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3623 if(candidates->empty())
3624 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3625 std::vector<int> nodes;
3626 DataArrayInt *cellIds1D=0;
3627 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3628 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3630 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3632 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3633 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3634 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3635 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3637 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3638 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3640 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3641 int ncellsSub=subMesh->getNumberOfCells();
3642 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3643 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3644 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3645 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3648 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3649 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3650 for(int i=0;i<ncellsSub;i++)
3652 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3654 if(cut3DSurf[i].first!=-2)
3656 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3657 connI->pushBackSilent(conn->getNumberOfTuples());
3658 cellIds2->pushBackSilent(i);
3662 int cellId3DSurf=cut3DSurf[i].second;
3663 int offset=nodalI[cellId3DSurf]+1;
3664 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3665 for(int j=0;j<nbOfEdges;j++)
3667 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3668 connI->pushBackSilent(conn->getNumberOfTuples());
3669 cellIds2->pushBackSilent(cellId3DSurf);
3674 if(cellIds2->empty())
3675 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3676 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3677 ret->setCoords(mDesc1->getCoords());
3678 ret->setConnectivity(conn,connI,true);
3679 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3684 * Finds cells whose bounding boxes intersect a given plane.
3685 * \param [in] origin - 3 components of a point defining location of the plane.
3686 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3687 * must be greater than 1e-6.
3688 * \param [in] eps - half-thickness of the plane.
3689 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3690 * cells. The caller is to delete this array using decrRef() as it is no more
3692 * \throw If the coordinates array is not set.
3693 * \throw If the nodal connectivity of cells is not defined.
3694 * \throw If \a this->getSpaceDimension() != 3.
3695 * \throw If magnitude of \a vec is less than 1e-6.
3696 * \sa buildSlice3D()
3698 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3700 checkFullyDefined();
3701 if(getSpaceDimension()!=3)
3702 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3703 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3705 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3707 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3708 double angle=acos(vec[2]/normm);
3709 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3713 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3714 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3715 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3717 mw->getBoundingBox(bbox);
3718 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3719 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3723 getBoundingBox(bbox);
3724 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3725 cellIds=getCellsInBoundingBox(bbox,eps);
3727 return cellIds.retn();
3731 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3732 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3733 * No consideration of coordinate is done by this method.
3734 * 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)
3735 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3737 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3739 if(getMeshDimension()!=1)
3740 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3741 int nbCells=getNumberOfCells();
3743 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3744 const int *connI=_nodal_connec_index->getConstPointer();
3745 const int *conn=_nodal_connec->getConstPointer();
3746 int ref=conn[connI[0]+2];
3747 for(int i=1;i<nbCells;i++)
3749 if(conn[connI[i]+1]!=ref)
3751 ref=conn[connI[i]+2];
3757 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3758 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3759 * \param pt reference point of the line
3760 * \param v normalized director vector of the line
3761 * \param eps max precision before throwing an exception
3762 * \param res output of size this->getNumberOfCells
3764 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3766 if(getMeshDimension()!=1)
3767 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3768 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3769 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3770 if(getSpaceDimension()!=3)
3771 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3772 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3773 const double *fPtr=f->getArray()->getConstPointer();
3775 for(int i=0;i<getNumberOfCells();i++)
3777 const double *tmp1=fPtr+3*i;
3778 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3779 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3780 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3781 double n1=INTERP_KERNEL::norm<3>(tmp);
3782 n1/=INTERP_KERNEL::norm<3>(tmp1);
3784 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3786 const double *coo=getCoords()->getConstPointer();
3787 for(int i=0;i<getNumberOfNodes();i++)
3789 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3790 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3791 res[i]=std::accumulate(tmp,tmp+3,0.);
3796 * 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.
3797 * \a this is expected to be a mesh so that its space dimension is equal to its
3798 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3799 * 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).
3801 * 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
3802 * 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).
3803 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3805 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3806 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3808 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3809 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3810 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3811 * \return the positive value of the distance.
3812 * \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
3814 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3816 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3818 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3819 if(meshDim!=spaceDim-1)
3820 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3821 if(meshDim!=2 && meshDim!=1)
3822 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3823 checkFullyDefined();
3824 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3825 { 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()); }
3826 DataArrayInt *ret1=0;
3827 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3828 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3830 cellId=*ret1Safe->begin();
3831 return *ret0->begin();
3835 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3836 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3837 * 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
3838 * 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).
3839 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3841 * \a this is expected to be a mesh so that its space dimension is equal to its
3842 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3843 * 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).
3845 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3846 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3848 * \param [in] pts the list of points in which each tuple represents a point
3849 * \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.
3850 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3851 * \throw if number of components of \a pts is not equal to the space dimension.
3852 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3853 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3855 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3858 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3859 pts->checkAllocated();
3860 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3861 if(meshDim!=spaceDim-1)
3862 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3863 if(meshDim!=2 && meshDim!=1)
3864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3865 if(pts->getNumberOfComponents()!=spaceDim)
3867 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3868 throw INTERP_KERNEL::Exception(oss.str().c_str());
3870 checkFullyDefined();
3871 int nbCells=getNumberOfCells();
3873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3874 int nbOfPts=pts->getNumberOfTuples();
3875 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3877 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3878 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3879 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3880 const double *bbox(bboxArr->begin());
3885 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3886 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3888 double x=std::numeric_limits<double>::max();
3889 std::vector<int> elems;
3890 myTree.getMinDistanceOfMax(ptsPtr,x);
3891 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3892 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3898 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3899 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3901 double x=std::numeric_limits<double>::max();
3902 std::vector<int> elems;
3903 myTree.getMinDistanceOfMax(ptsPtr,x);
3904 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3905 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3910 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3912 cellIds=ret1.retn();
3917 * \param [in] pt the start pointer (included) of the coordinates of the point
3918 * \param [in] cellIdsBg the start pointer (included) of cellIds
3919 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3920 * \param [in] nc nodal connectivity
3921 * \param [in] ncI nodal connectivity index
3922 * \param [in,out] ret0 the min distance between \a this and the external input point
3923 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3924 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3926 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)
3929 ret0=std::numeric_limits<double>::max();
3930 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3932 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3934 case INTERP_KERNEL::NORM_TRI3:
3936 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3938 { ret0=tmp; cellId=*zeCell; }
3941 case INTERP_KERNEL::NORM_QUAD4:
3942 case INTERP_KERNEL::NORM_POLYGON:
3944 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3946 { ret0=tmp; cellId=*zeCell; }
3950 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3956 * \param [in] pt the start pointer (included) of the coordinates of the point
3957 * \param [in] cellIdsBg the start pointer (included) of cellIds
3958 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3959 * \param [in] nc nodal connectivity
3960 * \param [in] ncI nodal connectivity index
3961 * \param [in,out] ret0 the min distance between \a this and the external input point
3962 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3963 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3965 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)
3968 ret0=std::numeric_limits<double>::max();
3969 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3971 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3973 case INTERP_KERNEL::NORM_SEG2:
3975 std::size_t uselessEntry=0;
3976 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3979 { ret0=tmp; cellId=*zeCell; }
3983 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3989 * Finds cells in contact with a ball (i.e. a point with precision).
3990 * \warning This method is suitable if the caller intends to evaluate only one
3991 * point, for more points getCellsContainingPoints() is recommended as it is
3993 * \param [in] pos - array of coordinates of the ball central point.
3994 * \param [in] eps - ball radius.
3995 * \return int - a smallest id of cells being in contact with the ball, -1 in case
3996 * if there are no such cells.
3997 * \throw If the coordinates array is not set.
3998 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4000 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4002 std::vector<int> elts;
4003 getCellsContainingPoint(pos,eps,elts);
4006 return elts.front();
4010 * Finds cells in contact with a ball (i.e. a point with precision).
4011 * \warning This method is suitable if the caller intends to evaluate only one
4012 * point, for more points getCellsContainingPoints() is recommended as it is
4014 * \param [in] pos - array of coordinates of the ball central point.
4015 * \param [in] eps - ball radius.
4016 * \param [out] elts - vector returning ids of the found cells. It is cleared
4017 * before inserting ids.
4018 * \throw If the coordinates array is not set.
4019 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4021 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4022 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4024 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4026 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4027 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4028 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4033 namespace ParaMEDMEM
4035 template<const int SPACEDIMM>
4039 static const int MY_SPACEDIM=SPACEDIMM;
4040 static const int MY_MESHDIM=8;
4041 typedef int MyConnType;
4042 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4044 // useless, but for windows compilation ...
4045 const double* getCoordinatesPtr() const { return 0; }
4046 const int* getConnectivityPtr() const { return 0; }
4047 const int* getConnectivityIndexPtr() const { return 0; }
4048 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4052 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4054 INTERP_KERNEL::Edge *ret=0;
4057 case INTERP_KERNEL::NORM_SEG2:
4059 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4062 case INTERP_KERNEL::NORM_SEG3:
4064 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4065 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4066 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4067 bool colinearity=inters.areColinears();
4068 delete e1; delete e2;
4070 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4072 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4073 mapp2[bg[2]].second=false;
4077 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4083 * 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'.
4084 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4085 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4087 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4090 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.
4091 const double *coo=mDesc->getCoords()->getConstPointer();
4092 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4093 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4095 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4096 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4097 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4099 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4100 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4102 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4103 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4105 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4106 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4108 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4110 if((*it2).second.second)
4111 mapp[(*it2).second.first]=(*it2).first;
4112 ((*it2).second.first)->decrRef();
4117 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4121 int locId=nodeId-offset2;
4122 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4126 int locId=nodeId-offset1;
4127 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4129 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4132 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4133 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4134 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4136 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4138 int eltId1=abs(*desc1)-1;
4139 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4141 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4142 if(it==mappRev.end())
4144 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4155 template<int SPACEDIM>
4156 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4157 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4159 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4160 int *eltsIndexPtr(eltsIndex->getPointer());
4161 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4162 const double *bbox(bboxArr->begin());
4163 int nbOfCells=getNumberOfCells();
4164 const int *conn=_nodal_connec->getConstPointer();
4165 const int *connI=_nodal_connec_index->getConstPointer();
4166 double bb[2*SPACEDIM];
4167 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4168 for(int i=0;i<nbOfPoints;i++)
4170 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4171 for(int j=0;j<SPACEDIM;j++)
4173 bb[2*j]=pos[SPACEDIM*i+j];
4174 bb[2*j+1]=pos[SPACEDIM*i+j];
4176 std::vector<int> candidates;
4177 myTree.getIntersectingElems(bb,candidates);
4178 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4180 int sz=connI[(*iter)+1]-connI[*iter]-1;
4181 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4182 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4183 coords,conn+connI[*iter]+1,sz,eps))
4185 eltsIndexPtr[i+1]++;
4186 elts->pushBackSilent(*iter);
4192 * Finds cells in contact with several balls (i.e. points with precision).
4193 * This method is an extension of getCellContainingPoint() and
4194 * getCellsContainingPoint() for the case of multiple points.
4195 * \param [in] pos - an array of coordinates of points in full interlace mode :
4196 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4197 * this->getSpaceDimension() * \a nbOfPoints
4198 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4199 * \param [in] eps - radius of balls (i.e. the precision).
4200 * \param [out] elts - vector returning ids of found cells.
4201 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4202 * dividing cell ids in \a elts into groups each referring to one
4203 * point. Its every element (except the last one) is an index pointing to the
4204 * first id of a group of cells. For example cells in contact with the *i*-th
4205 * point are described by following range of indices:
4206 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4207 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4208 * Number of cells in contact with the *i*-th point is
4209 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4210 * \throw If the coordinates array is not set.
4211 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4213 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4214 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4216 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4217 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4219 int spaceDim=getSpaceDimension();
4220 int mDim=getMeshDimension();
4225 const double *coords=_coords->getConstPointer();
4226 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4233 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4235 else if(spaceDim==2)
4239 const double *coords=_coords->getConstPointer();
4240 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4243 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4245 else if(spaceDim==1)
4249 const double *coords=_coords->getConstPointer();
4250 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4253 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4256 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4260 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4261 * least two its edges intersect each other anywhere except their extremities. An
4262 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4263 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4264 * cleared before filling in.
4265 * \param [in] eps - precision.
4266 * \throw If \a this->getMeshDimension() != 2.
4267 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4269 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4271 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4272 if(getMeshDimension()!=2)
4273 throw INTERP_KERNEL::Exception(msg);
4274 int spaceDim=getSpaceDimension();
4275 if(spaceDim!=2 && spaceDim!=3)
4276 throw INTERP_KERNEL::Exception(msg);
4277 const int *conn=_nodal_connec->getConstPointer();
4278 const int *connI=_nodal_connec_index->getConstPointer();
4279 int nbOfCells=getNumberOfCells();
4280 std::vector<double> cell2DinS2;
4281 for(int i=0;i<nbOfCells;i++)
4283 int offset=connI[i];
4284 int nbOfNodesForCell=connI[i+1]-offset-1;
4285 if(nbOfNodesForCell<=3)
4287 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4288 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4289 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4296 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4298 * 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.
4299 * 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.
4301 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4302 * This convex envelop is computed using Jarvis march algorithm.
4303 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4304 * 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)
4305 * 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.
4307 * \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.
4309 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4311 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4313 checkFullyDefined();
4314 const double *coords=getCoords()->getConstPointer();
4315 int nbOfCells=getNumberOfCells();
4316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4317 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4319 int *workIndexOut=nodalConnecIndexOut->getPointer();
4321 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4322 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4323 std::set<INTERP_KERNEL::NormalizedCellType> types;
4324 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4325 isChanged->alloc(0,1);
4326 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4328 int pos=nodalConnecOut->getNumberOfTuples();
4329 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4330 isChanged->pushBackSilent(i);
4331 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4332 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4334 if(isChanged->empty())
4336 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4338 return isChanged.retn();
4342 * This method is \b NOT const because it can modify \a this.
4343 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4344 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4345 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4346 * \b 1 for translation and rotation around point of 'mesh1D'.
4347 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4349 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4351 checkFullyDefined();
4352 mesh1D->checkFullyDefined();
4353 if(!mesh1D->isContiguous1D())
4354 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4355 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4356 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4357 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4358 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4359 if(mesh1D->getMeshDimension()!=1)
4360 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4362 if(isPresenceOfQuadratic())
4364 if(mesh1D->isFullyQuadratic())
4367 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4370 int oldNbOfNodes=getNumberOfNodes();
4371 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4376 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4381 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4385 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4387 setCoords(newCoords);
4388 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4394 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4395 * If it is not the case an exception will be thrown.
4396 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4397 * intersection of plane defined by ('origin','vec').
4398 * This method has one in/out parameter : 'cut3DCurve'.
4399 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4400 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4401 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4402 * This method will throw an exception if \a this contains a non linear segment.
4404 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4406 checkFullyDefined();
4407 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4409 int ncells=getNumberOfCells();
4410 int nnodes=getNumberOfNodes();
4411 double vec2[3],vec3[3],vec4[3];
4412 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4415 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4416 const int *conn=_nodal_connec->getConstPointer();
4417 const int *connI=_nodal_connec_index->getConstPointer();
4418 const double *coo=_coords->getConstPointer();
4419 std::vector<double> addCoo;
4420 for(int i=0;i<ncells;i++)
4422 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4424 if(cut3DCurve[i]==-2)
4426 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4427 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];
4428 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4429 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4430 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4432 const double *st2=coo+3*st;
4433 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4434 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]));
4435 if(pos>eps && pos<1-eps)
4437 int nNode=((int)addCoo.size())/3;
4438 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4439 addCoo.insert(addCoo.end(),vec4,vec4+3);
4440 cut3DCurve[i]=nnodes+nNode;
4446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4450 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4451 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4452 coo2->alloc(newNbOfNodes,3);
4453 double *tmp=coo2->getPointer();
4454 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4455 std::copy(addCoo.begin(),addCoo.end(),tmp);
4456 DataArrayDouble::SetArrayIn(coo2,_coords);
4461 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4462 * \param mesh1D is the input 1D mesh used for translation computation.
4463 * \return newCoords new coords filled by this method.
4465 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4467 int oldNbOfNodes=getNumberOfNodes();
4468 int nbOf1DCells=mesh1D->getNumberOfCells();
4469 int spaceDim=getSpaceDimension();
4470 DataArrayDouble *ret=DataArrayDouble::New();
4471 std::vector<bool> isQuads;
4472 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4473 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4474 double *retPtr=ret->getPointer();
4475 const double *coords=getCoords()->getConstPointer();
4476 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4478 std::vector<double> c;
4482 for(int i=0;i<nbOf1DCells;i++)
4485 mesh1D->getNodeIdsOfCell(i,v);
4487 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4488 mesh1D->getCoordinatesOfNode(v[0],c);
4489 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4490 for(int j=0;j<oldNbOfNodes;j++)
4491 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4495 mesh1D->getCoordinatesOfNode(v[1],c);
4496 mesh1D->getCoordinatesOfNode(v[0],c);
4497 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4498 for(int j=0;j<oldNbOfNodes;j++)
4499 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4502 ret->copyStringInfoFrom(*getCoords());
4507 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4508 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4509 * \return newCoords new coords filled by this method.
4511 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4513 if(mesh1D->getSpaceDimension()==2)
4514 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4515 if(mesh1D->getSpaceDimension()==3)
4516 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4517 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4521 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4522 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4523 * \return newCoords new coords filled by this method.
4525 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4528 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4529 int oldNbOfNodes=getNumberOfNodes();
4530 int nbOf1DCells=mesh1D->getNumberOfCells();
4532 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4533 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4534 int nbOfLevsInVec=nbOf1DCells+1;
4535 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4536 double *retPtr=ret->getPointer();
4537 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4538 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4539 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4540 tmp->setCoords(tmp2);
4541 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4542 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4543 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4544 for(int i=1;i<nbOfLevsInVec;i++)
4546 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4547 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4548 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4549 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4550 tmp->translate(vec);
4551 double tmp3[2],radius,alpha,alpha0;
4552 const double *p0=i+1<nbOfLevsInVec?begin:third;
4553 const double *p1=i+1<nbOfLevsInVec?end:begin;
4554 const double *p2=i+1<nbOfLevsInVec?third:end;
4555 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4556 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]);
4557 double angle=acos(cosangle/(radius*radius));
4558 tmp->rotate(end,0,angle);
4559 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4565 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4566 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4567 * \return newCoords new coords filled by this method.
4569 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4572 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4573 int oldNbOfNodes=getNumberOfNodes();
4574 int nbOf1DCells=mesh1D->getNumberOfCells();
4576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4577 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4578 int nbOfLevsInVec=nbOf1DCells+1;
4579 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4580 double *retPtr=ret->getPointer();
4581 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4582 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4583 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4584 tmp->setCoords(tmp2);
4585 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4586 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4587 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4588 for(int i=1;i<nbOfLevsInVec;i++)
4590 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4591 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4592 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4593 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4594 tmp->translate(vec);
4595 double tmp3[2],radius,alpha,alpha0;
4596 const double *p0=i+1<nbOfLevsInVec?begin:third;
4597 const double *p1=i+1<nbOfLevsInVec?end:begin;
4598 const double *p2=i+1<nbOfLevsInVec?third:end;
4599 double vecPlane[3]={
4600 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4601 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4602 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4604 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4607 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4608 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4609 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4611 double c2=cos(asin(s2));
4613 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4614 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4615 {-vec2[1]*s2, vec2[0]*s2, c2}
4617 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]};
4618 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]};
4619 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]};
4620 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4621 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]);
4622 double angle=acos(cosangle/(radius*radius));
4623 tmp->rotate(end,vecPlane,angle);
4626 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4632 * This method is private because not easy to use for end user. This method is const contrary to
4633 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4634 * the coords sorted slice by slice.
4635 * \param isQuad specifies presence of quadratic cells.
4637 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4639 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4640 int nbOf2DCells=getNumberOfCells();
4641 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4642 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4643 const int *conn=_nodal_connec->getConstPointer();
4644 const int *connI=_nodal_connec_index->getConstPointer();
4645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4647 newConnI->alloc(nbOf3DCells+1,1);
4648 int *newConnIPtr=newConnI->getPointer();
4650 std::vector<int> newc;
4651 for(int j=0;j<nbOf2DCells;j++)
4653 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4654 *newConnIPtr++=(int)newc.size();
4656 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4657 int *newConnPtr=newConn->getPointer();
4658 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4659 newConnIPtr=newConnI->getPointer();
4660 for(int iz=0;iz<nbOf1DCells;iz++)
4663 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4664 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4666 int icell=(int)(iter-newc.begin());
4667 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4670 *newConnPtr=(*iter)+iz*deltaPerLev;
4675 *newConnPtr=(*iter);
4678 ret->setConnectivity(newConn,newConnI,true);
4679 ret->setCoords(getCoords());
4684 * Checks if \a this mesh is constituted by only quadratic cells.
4685 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4686 * \throw If the coordinates array is not set.
4687 * \throw If the nodal connectivity of cells is not defined.
4689 bool MEDCouplingUMesh::isFullyQuadratic() const
4691 checkFullyDefined();
4693 int nbOfCells=getNumberOfCells();
4694 for(int i=0;i<nbOfCells && ret;i++)
4696 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4697 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4698 ret=cm.isQuadratic();
4704 * Checks if \a this mesh includes any quadratic cell.
4705 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4706 * \throw If the coordinates array is not set.
4707 * \throw If the nodal connectivity of cells is not defined.
4709 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4711 checkFullyDefined();
4713 int nbOfCells=getNumberOfCells();
4714 for(int i=0;i<nbOfCells && !ret;i++)
4716 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4717 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4718 ret=cm.isQuadratic();
4724 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4725 * this mesh, it remains unchanged.
4726 * \throw If the coordinates array is not set.
4727 * \throw If the nodal connectivity of cells is not defined.
4729 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4731 checkFullyDefined();
4732 int nbOfCells=getNumberOfCells();
4734 const int *iciptr=_nodal_connec_index->getConstPointer();
4735 for(int i=0;i<nbOfCells;i++)
4737 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4738 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4739 if(cm.isQuadratic())
4741 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4742 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4743 if(!cml.isDynamic())
4744 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4746 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4753 const int *icptr=_nodal_connec->getConstPointer();
4754 newConn->alloc(getMeshLength()-delta,1);
4755 newConnI->alloc(nbOfCells+1,1);
4756 int *ocptr=newConn->getPointer();
4757 int *ociptr=newConnI->getPointer();
4760 for(int i=0;i<nbOfCells;i++,ociptr++)
4762 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4763 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4764 if(!cm.isQuadratic())
4766 _types.insert(type);
4767 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4768 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4772 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4773 _types.insert(typel);
4774 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4775 int newNbOfNodes=cml.getNumberOfNodes();
4777 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4778 *ocptr++=(int)typel;
4779 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4780 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4783 setConnectivity(newConn,newConnI,false);
4787 * This method converts all linear cell in \a this to quadratic one.
4788 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4789 * 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)
4790 * 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.
4791 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4792 * end of the existing coordinates.
4794 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4795 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4796 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4798 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4800 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4802 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4804 DataArrayInt *conn=0,*connI=0;
4805 DataArrayDouble *coords=0;
4806 std::set<INTERP_KERNEL::NormalizedCellType> types;
4807 checkFullyDefined();
4808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4809 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4810 int meshDim=getMeshDimension();
4811 switch(conversionType)
4817 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4818 connSafe=conn; connISafe=connI; coordsSafe=coords;
4821 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4822 connSafe=conn; connISafe=connI; coordsSafe=coords;
4825 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4826 connSafe=conn; connISafe=connI; coordsSafe=coords;
4829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4837 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4838 connSafe=conn; connISafe=connI; coordsSafe=coords;
4841 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4842 connSafe=conn; connISafe=connI; coordsSafe=coords;
4845 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4846 connSafe=conn; connISafe=connI; coordsSafe=coords;
4849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4854 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4856 setConnectivity(connSafe,connISafe,false);
4858 setCoords(coordsSafe);
4863 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4864 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4865 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4867 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4869 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4870 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4872 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4873 int nbOfCells=getNumberOfCells();
4874 int nbOfNodes=getNumberOfNodes();
4875 const int *cPtr=_nodal_connec->getConstPointer();
4876 const int *icPtr=_nodal_connec_index->getConstPointer();
4877 int lastVal=0,offset=nbOfNodes;
4878 for(int i=0;i<nbOfCells;i++,icPtr++)
4880 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4881 if(type==INTERP_KERNEL::NORM_SEG2)
4883 types.insert(INTERP_KERNEL::NORM_SEG3);
4884 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4885 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4886 newConn->pushBackSilent(offset++);
4888 newConnI->pushBackSilent(lastVal);
4889 ret->pushBackSilent(i);
4894 lastVal+=(icPtr[1]-icPtr[0]);
4895 newConnI->pushBackSilent(lastVal);
4896 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4899 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4900 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4904 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)
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4910 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4911 DataArrayInt *conn1D=0,*conn1DI=0;
4912 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4913 DataArrayDouble *coordsTmp=0;
4914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4915 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4917 const int *c1DPtr=conn1D->begin();
4918 const int *c1DIPtr=conn1DI->begin();
4919 int nbOfCells=getNumberOfCells();
4920 const int *cPtr=_nodal_connec->getConstPointer();
4921 const int *icPtr=_nodal_connec_index->getConstPointer();
4923 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4925 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4926 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4927 if(!cm.isQuadratic())
4929 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4930 types.insert(typ2); newConn->pushBackSilent(typ2);
4931 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4932 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4933 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4934 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4935 newConnI->pushBackSilent(lastVal);
4936 ret->pushBackSilent(i);
4941 lastVal+=(icPtr[1]-icPtr[0]);
4942 newConnI->pushBackSilent(lastVal);
4943 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4946 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4951 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4952 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4953 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4955 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4958 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4959 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4960 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4963 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4966 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4972 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4973 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4974 DataArrayInt *conn1D=0,*conn1DI=0;
4975 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4976 DataArrayDouble *coordsTmp=0;
4977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4978 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4980 const int *c1DPtr=conn1D->begin();
4981 const int *c1DIPtr=conn1DI->begin();
4982 int nbOfCells=getNumberOfCells();
4983 const int *cPtr=_nodal_connec->getConstPointer();
4984 const int *icPtr=_nodal_connec_index->getConstPointer();
4985 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4986 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4988 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4989 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4990 if(!cm.isQuadratic())
4992 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4993 types.insert(typ2); newConn->pushBackSilent(typ2);
4994 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4995 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4996 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4997 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4998 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4999 newConnI->pushBackSilent(lastVal);
5000 ret->pushBackSilent(i);
5005 lastVal+=(icPtr[1]-icPtr[0]);
5006 newConnI->pushBackSilent(lastVal);
5007 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5010 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5011 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5016 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5017 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5018 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5020 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5022 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5023 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5024 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5027 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5029 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5030 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5032 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5034 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5038 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5039 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5040 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5041 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5042 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5043 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5044 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5045 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5046 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5047 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5049 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5050 int nbOfCells=getNumberOfCells();
5051 const int *cPtr=_nodal_connec->getConstPointer();
5052 const int *icPtr=_nodal_connec_index->getConstPointer();
5053 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5054 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5056 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5057 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5058 if(!cm.isQuadratic())
5060 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5061 if(typ2==INTERP_KERNEL::NORM_ERROR)
5063 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5064 throw INTERP_KERNEL::Exception(oss.str().c_str());
5066 types.insert(typ2); newConn->pushBackSilent(typ2);
5067 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5068 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5069 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5070 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5072 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5073 int tmpPos=newConn->getNumberOfTuples();
5074 newConn->pushBackSilent(nodeId2);
5075 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5077 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5078 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5079 newConnI->pushBackSilent(lastVal);
5080 ret->pushBackSilent(i);
5085 lastVal+=(icPtr[1]-icPtr[0]);
5086 newConnI->pushBackSilent(lastVal);
5087 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5091 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5092 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5093 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5094 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5095 int *c=newConn->getPointer();
5096 const int *cI(newConnI->begin());
5097 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5098 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5099 offset=coordsTmp2Safe->getNumberOfTuples();
5100 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5101 c[cI[(*elt)+1]-1]+=offset;
5102 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5107 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5108 * so that the number of cells remains the same. Quadratic faces are converted to
5109 * polygons. This method works only for 2D meshes in
5110 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5111 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5112 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5113 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5114 * a polylinized edge constituting the input polygon.
5115 * \throw If the coordinates array is not set.
5116 * \throw If the nodal connectivity of cells is not defined.
5117 * \throw If \a this->getMeshDimension() != 2.
5118 * \throw If \a this->getSpaceDimension() != 2.
5120 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5122 checkFullyDefined();
5123 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5124 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5125 double epsa=fabs(eps);
5126 if(epsa<std::numeric_limits<double>::min())
5127 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 !");
5128 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5129 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5131 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5132 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5133 revDesc1=0; revDescIndx1=0;
5134 mDesc->tessellate2DCurve(eps);
5135 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5136 setCoords(mDesc->getCoords());
5140 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5141 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5142 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5143 * a sub-divided edge.
5144 * \throw If the coordinates array is not set.
5145 * \throw If the nodal connectivity of cells is not defined.
5146 * \throw If \a this->getMeshDimension() != 1.
5147 * \throw If \a this->getSpaceDimension() != 2.
5149 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5151 checkFullyDefined();
5152 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5154 double epsa=fabs(eps);
5155 if(epsa<std::numeric_limits<double>::min())
5156 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 !");
5157 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5158 int nbCells=getNumberOfCells();
5159 int nbNodes=getNumberOfNodes();
5160 const int *conn=_nodal_connec->getConstPointer();
5161 const int *connI=_nodal_connec_index->getConstPointer();
5162 const double *coords=_coords->getConstPointer();
5163 std::vector<double> addCoo;
5164 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5166 newConnI->alloc(nbCells+1,1);
5167 int *newConnIPtr=newConnI->getPointer();
5170 INTERP_KERNEL::Node *tmp2[3];
5171 std::set<INTERP_KERNEL::NormalizedCellType> types;
5172 for(int i=0;i<nbCells;i++,newConnIPtr++)
5174 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5175 if(cm.isQuadratic())
5176 {//assert(connI[i+1]-connI[i]-1==3)
5177 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5178 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5179 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5180 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5181 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5184 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5185 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5187 newConnIPtr[1]=(int)newConn.size();
5191 types.insert(INTERP_KERNEL::NORM_SEG2);
5192 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5193 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5194 newConnIPtr[1]=newConnIPtr[0]+3;
5199 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5200 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5201 newConnIPtr[1]=newConnIPtr[0]+3;
5204 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5207 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5209 newConnArr->alloc((int)newConn.size(),1);
5210 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5211 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5212 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5213 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5214 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5215 std::copy(addCoo.begin(),addCoo.end(),work);
5216 DataArrayDouble::SetArrayIn(newCoords,_coords);
5221 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5222 * In addition, returns an array mapping new cells to old ones. <br>
5223 * This method typically increases the number of cells in \a this mesh
5224 * but the number of nodes remains \b unchanged.
5225 * That's why the 3D splitting policies
5226 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5227 * \param [in] policy - specifies a pattern used for splitting.
5228 * The semantic of \a policy is:
5229 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5230 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5231 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5232 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5233 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5234 * an id of old cell producing it. The caller is to delete this array using
5235 * decrRef() as it is no more needed.
5236 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5237 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5238 * and \a this->getMeshDimension() != 3.
5239 * \throw If \a policy is not one of the four discussed above.
5240 * \throw If the nodal connectivity of cells is not defined.
5241 * \sa MEDCouplingUMesh::tetrahedrize
5243 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5248 return simplexizePol0();
5250 return simplexizePol1();
5251 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5252 return simplexizePlanarFace5();
5253 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5254 return simplexizePlanarFace6();
5256 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)");
5261 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5262 * - 1D: INTERP_KERNEL::NORM_SEG2
5263 * - 2D: INTERP_KERNEL::NORM_TRI3
5264 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5266 * This method is useful for users that need to use P1 field services as
5267 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5268 * All these methods need mesh support containing only simplex cells.
5269 * \return bool - \c true if there are only simplex cells in \a this mesh.
5270 * \throw If the coordinates array is not set.
5271 * \throw If the nodal connectivity of cells is not defined.
5272 * \throw If \a this->getMeshDimension() < 1.
5274 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5276 checkFullyDefined();
5277 int mdim=getMeshDimension();
5278 if(mdim<1 || mdim>3)
5279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5280 int nbCells=getNumberOfCells();
5281 const int *conn=_nodal_connec->getConstPointer();
5282 const int *connI=_nodal_connec_index->getConstPointer();
5283 for(int i=0;i<nbCells;i++)
5285 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5293 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5295 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5297 checkConnectivityFullyDefined();
5298 if(getMeshDimension()!=2)
5299 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5300 int nbOfCells=getNumberOfCells();
5301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5302 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5303 ret->alloc(nbOfCells+nbOfCutCells,1);
5304 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5305 int *retPt=ret->getPointer();
5306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5308 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5309 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5310 int *pt=newConn->getPointer();
5311 int *ptI=newConnI->getPointer();
5313 const int *oldc=_nodal_connec->getConstPointer();
5314 const int *ci=_nodal_connec_index->getConstPointer();
5315 for(int i=0;i<nbOfCells;i++,ci++)
5317 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5319 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5320 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5321 pt=std::copy(tmp,tmp+8,pt);
5330 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5331 ptI[1]=ptI[0]+ci[1]-ci[0];
5336 _nodal_connec->decrRef();
5337 _nodal_connec=newConn.retn();
5338 _nodal_connec_index->decrRef();
5339 _nodal_connec_index=newConnI.retn();
5346 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5348 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5350 checkConnectivityFullyDefined();
5351 if(getMeshDimension()!=2)
5352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5353 int nbOfCells=getNumberOfCells();
5354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5355 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5356 ret->alloc(nbOfCells+nbOfCutCells,1);
5357 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5358 int *retPt=ret->getPointer();
5359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5361 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5362 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5363 int *pt=newConn->getPointer();
5364 int *ptI=newConnI->getPointer();
5366 const int *oldc=_nodal_connec->getConstPointer();
5367 const int *ci=_nodal_connec_index->getConstPointer();
5368 for(int i=0;i<nbOfCells;i++,ci++)
5370 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5372 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5373 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5374 pt=std::copy(tmp,tmp+8,pt);
5383 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5384 ptI[1]=ptI[0]+ci[1]-ci[0];
5389 _nodal_connec->decrRef();
5390 _nodal_connec=newConn.retn();
5391 _nodal_connec_index->decrRef();
5392 _nodal_connec_index=newConnI.retn();
5399 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5401 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5403 checkConnectivityFullyDefined();
5404 if(getMeshDimension()!=3)
5405 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5406 int nbOfCells=getNumberOfCells();
5407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5408 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5409 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5410 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5411 int *retPt=ret->getPointer();
5412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5414 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5415 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5416 int *pt=newConn->getPointer();
5417 int *ptI=newConnI->getPointer();
5419 const int *oldc=_nodal_connec->getConstPointer();
5420 const int *ci=_nodal_connec_index->getConstPointer();
5421 for(int i=0;i<nbOfCells;i++,ci++)
5423 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5425 for(int j=0;j<5;j++,pt+=5,ptI++)
5427 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5428 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];
5435 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5436 ptI[1]=ptI[0]+ci[1]-ci[0];
5441 _nodal_connec->decrRef();
5442 _nodal_connec=newConn.retn();
5443 _nodal_connec_index->decrRef();
5444 _nodal_connec_index=newConnI.retn();
5451 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5453 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5455 checkConnectivityFullyDefined();
5456 if(getMeshDimension()!=3)
5457 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5458 int nbOfCells=getNumberOfCells();
5459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5460 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5461 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5462 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5463 int *retPt=ret->getPointer();
5464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5466 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5467 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5468 int *pt=newConn->getPointer();
5469 int *ptI=newConnI->getPointer();
5471 const int *oldc=_nodal_connec->getConstPointer();
5472 const int *ci=_nodal_connec_index->getConstPointer();
5473 for(int i=0;i<nbOfCells;i++,ci++)
5475 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5477 for(int j=0;j<6;j++,pt+=5,ptI++)
5479 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5480 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];
5487 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5488 ptI[1]=ptI[0]+ci[1]-ci[0];
5493 _nodal_connec->decrRef();
5494 _nodal_connec=newConn.retn();
5495 _nodal_connec_index->decrRef();
5496 _nodal_connec_index=newConnI.retn();
5503 * 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.
5504 * This method completly ignore coordinates.
5505 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5506 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5507 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5508 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5510 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5512 checkFullyDefined();
5513 if(getMeshDimension()!=2)
5514 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5515 int nbOfCells=getNumberOfCells();
5516 int *connI=_nodal_connec_index->getPointer();
5518 for(int i=0;i<nbOfCells;i++,connI++)
5520 int offset=descIndex[i];
5521 int nbOfEdges=descIndex[i+1]-offset;
5523 bool ddirect=desc[offset+nbOfEdges-1]>0;
5524 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5525 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5526 for(int j=0;j<nbOfEdges;j++)
5528 bool direct=desc[offset+j]>0;
5529 int edgeId=std::abs(desc[offset+j])-1;
5530 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5532 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5533 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5534 int ref2=direct?id1:id2;
5537 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5538 newConnLgth+=nbOfSubNodes-1;
5543 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5544 throw INTERP_KERNEL::Exception(oss.str().c_str());
5549 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5552 newConnLgth++;//+1 is for cell type
5553 connI[1]=newConnLgth;
5556 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5557 newConn->alloc(newConnLgth,1);
5558 int *work=newConn->getPointer();
5559 for(int i=0;i<nbOfCells;i++)
5561 *work++=INTERP_KERNEL::NORM_POLYGON;
5562 int offset=descIndex[i];
5563 int nbOfEdges=descIndex[i+1]-offset;
5564 for(int j=0;j<nbOfEdges;j++)
5566 bool direct=desc[offset+j]>0;
5567 int edgeId=std::abs(desc[offset+j])-1;
5569 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5572 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5573 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5574 work=std::copy(it,it+nbOfSubNodes-1,work);
5578 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5581 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5585 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5586 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5587 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5588 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5589 * so it can be useful to call mergeNodes() before calling this method.
5590 * \throw If \a this->getMeshDimension() <= 1.
5591 * \throw If the coordinates array is not set.
5592 * \throw If the nodal connectivity of cells is not defined.
5594 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5596 checkFullyDefined();
5597 if(getMeshDimension()<=1)
5598 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5599 int nbOfCells=getNumberOfCells();
5602 int initMeshLgth=getMeshLength();
5603 int *conn=_nodal_connec->getPointer();
5604 int *index=_nodal_connec_index->getPointer();
5608 for(int i=0;i<nbOfCells;i++)
5610 lgthOfCurCell=index[i+1]-posOfCurCell;
5611 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5613 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5614 conn+newPos+1,newLgth);
5615 conn[newPos]=newType;
5617 posOfCurCell=index[i+1];
5620 if(newPos!=initMeshLgth)
5621 _nodal_connec->reAlloc(newPos);
5626 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5627 * A cell is considered to be oriented correctly if an angle between its
5628 * normal vector and a given vector is less than \c PI / \c 2.
5629 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5631 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5633 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5634 * is not cleared before filling in.
5635 * \throw If \a this->getMeshDimension() != 2.
5636 * \throw If \a this->getSpaceDimension() != 3.
5638 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5639 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5641 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5643 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5644 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5645 int nbOfCells=getNumberOfCells();
5646 const int *conn=_nodal_connec->getConstPointer();
5647 const int *connI=_nodal_connec_index->getConstPointer();
5648 const double *coordsPtr=_coords->getConstPointer();
5649 for(int i=0;i<nbOfCells;i++)
5651 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5652 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5654 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5655 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5662 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5663 * considered to be oriented correctly if an angle between its normal vector and a
5664 * given vector is less than \c PI / \c 2.
5665 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5667 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5669 * \throw If \a this->getMeshDimension() != 2.
5670 * \throw If \a this->getSpaceDimension() != 3.
5672 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5673 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5675 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5677 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5678 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5679 int nbOfCells=getNumberOfCells();
5680 int *conn=_nodal_connec->getPointer();
5681 const int *connI=_nodal_connec_index->getConstPointer();
5682 const double *coordsPtr=_coords->getConstPointer();
5683 bool isModified=false;
5684 for(int i=0;i<nbOfCells;i++)
5686 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5687 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5689 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5690 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5693 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5694 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5695 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5700 _nodal_connec->declareAsNew();
5705 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5706 * oriented facets. The normal vector of the facet should point out of the cell.
5707 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5708 * is not cleared before filling in.
5709 * \throw If \a this->getMeshDimension() != 3.
5710 * \throw If \a this->getSpaceDimension() != 3.
5711 * \throw If the coordinates array is not set.
5712 * \throw If the nodal connectivity of cells is not defined.
5714 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5715 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5717 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5719 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5720 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5721 int nbOfCells=getNumberOfCells();
5722 const int *conn=_nodal_connec->getConstPointer();
5723 const int *connI=_nodal_connec_index->getConstPointer();
5724 const double *coordsPtr=_coords->getConstPointer();
5725 for(int i=0;i<nbOfCells;i++)
5727 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5728 if(type==INTERP_KERNEL::NORM_POLYHED)
5730 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5737 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5739 * \throw If \a this->getMeshDimension() != 3.
5740 * \throw If \a this->getSpaceDimension() != 3.
5741 * \throw If the coordinates array is not set.
5742 * \throw If the nodal connectivity of cells is not defined.
5743 * \throw If the reparation fails.
5745 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5746 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5747 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5749 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5751 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5752 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5753 int nbOfCells=getNumberOfCells();
5754 int *conn=_nodal_connec->getPointer();
5755 const int *connI=_nodal_connec_index->getConstPointer();
5756 const double *coordsPtr=_coords->getConstPointer();
5757 for(int i=0;i<nbOfCells;i++)
5759 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5760 if(type==INTERP_KERNEL::NORM_POLYHED)
5764 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5765 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5767 catch(INTERP_KERNEL::Exception& e)
5769 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5770 throw INTERP_KERNEL::Exception(oss.str().c_str());
5778 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5779 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5780 * according to which the first facet of the cell should be oriented to have the normal vector
5781 * pointing out of cell.
5782 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5783 * cells. The caller is to delete this array using decrRef() as it is no more
5785 * \throw If \a this->getMeshDimension() != 3.
5786 * \throw If \a this->getSpaceDimension() != 3.
5787 * \throw If the coordinates array is not set.
5788 * \throw If the nodal connectivity of cells is not defined.
5790 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5791 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5792 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5794 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5796 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5797 if(getMeshDimension()!=3)
5798 throw INTERP_KERNEL::Exception(msg);
5799 int spaceDim=getSpaceDimension();
5801 throw INTERP_KERNEL::Exception(msg);
5803 int nbOfCells=getNumberOfCells();
5804 int *conn=_nodal_connec->getPointer();
5805 const int *connI=_nodal_connec_index->getConstPointer();
5806 const double *coo=getCoords()->getConstPointer();
5807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5808 for(int i=0;i<nbOfCells;i++)
5810 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5811 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5813 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5815 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5816 cells->pushBackSilent(i);
5820 return cells.retn();
5824 * This method is a faster method to correct orientation of all 3D cells in \a this.
5825 * 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.
5826 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5828 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5829 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5831 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5833 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5834 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5835 int nbOfCells=getNumberOfCells();
5836 int *conn=_nodal_connec->getPointer();
5837 const int *connI=_nodal_connec_index->getConstPointer();
5838 const double *coordsPtr=_coords->getConstPointer();
5839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5840 for(int i=0;i<nbOfCells;i++)
5842 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5845 case INTERP_KERNEL::NORM_TETRA4:
5847 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5849 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5850 ret->pushBackSilent(i);
5854 case INTERP_KERNEL::NORM_PYRA5:
5856 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5858 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5859 ret->pushBackSilent(i);
5863 case INTERP_KERNEL::NORM_PENTA6:
5864 case INTERP_KERNEL::NORM_HEXA8:
5865 case INTERP_KERNEL::NORM_HEXGP12:
5867 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5869 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5870 ret->pushBackSilent(i);
5874 case INTERP_KERNEL::NORM_POLYHED:
5876 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5878 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5879 ret->pushBackSilent(i);
5884 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 !");
5892 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5893 * If it is not the case an exception will be thrown.
5894 * This method is fast because the first cell of \a this is used to compute the plane.
5895 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5896 * \param pos output of size at least 3 used to store a point owned of searched plane.
5898 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5900 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5901 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5902 const int *conn=_nodal_connec->getConstPointer();
5903 const int *connI=_nodal_connec_index->getConstPointer();
5904 const double *coordsPtr=_coords->getConstPointer();
5905 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5906 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5910 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5911 * cells. Currently cells of the following types are treated:
5912 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5913 * For a cell of other type an exception is thrown.
5914 * Space dimension of a 2D mesh can be either 2 or 3.
5915 * The Edge Ratio of a cell \f$t\f$ is:
5916 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5917 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5918 * the smallest edge lengths of \f$t\f$.
5919 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5920 * cells and one time, lying on \a this mesh. The caller is to delete this
5921 * field using decrRef() as it is no more needed.
5922 * \throw If the coordinates array is not set.
5923 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5924 * \throw If the connectivity data array has more than one component.
5925 * \throw If the connectivity data array has a named component.
5926 * \throw If the connectivity index data array has more than one component.
5927 * \throw If the connectivity index data array has a named component.
5928 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5929 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5930 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5932 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5935 int spaceDim=getSpaceDimension();
5936 int meshDim=getMeshDimension();
5937 if(spaceDim!=2 && spaceDim!=3)
5938 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5939 if(meshDim!=2 && meshDim!=3)
5940 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5941 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5943 int nbOfCells=getNumberOfCells();
5944 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5945 arr->alloc(nbOfCells,1);
5946 double *pt=arr->getPointer();
5947 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5948 const int *conn=_nodal_connec->getConstPointer();
5949 const int *connI=_nodal_connec_index->getConstPointer();
5950 const double *coo=_coords->getConstPointer();
5952 for(int i=0;i<nbOfCells;i++,pt++)
5954 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5957 case INTERP_KERNEL::NORM_TRI3:
5959 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5960 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5963 case INTERP_KERNEL::NORM_QUAD4:
5965 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5966 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5969 case INTERP_KERNEL::NORM_TETRA4:
5971 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5972 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5976 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5978 conn+=connI[i+1]-connI[i];
5980 ret->setName("EdgeRatio");
5981 ret->synchronizeTimeWithSupport();
5986 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5987 * cells. Currently cells of the following types are treated:
5988 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5989 * For a cell of other type an exception is thrown.
5990 * Space dimension of a 2D mesh can be either 2 or 3.
5991 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5992 * cells and one time, lying on \a this mesh. The caller is to delete this
5993 * field using decrRef() as it is no more needed.
5994 * \throw If the coordinates array is not set.
5995 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5996 * \throw If the connectivity data array has more than one component.
5997 * \throw If the connectivity data array has a named component.
5998 * \throw If the connectivity index data array has more than one component.
5999 * \throw If the connectivity index data array has a named component.
6000 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6001 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6002 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6004 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6007 int spaceDim=getSpaceDimension();
6008 int meshDim=getMeshDimension();
6009 if(spaceDim!=2 && spaceDim!=3)
6010 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6011 if(meshDim!=2 && meshDim!=3)
6012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6013 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6015 int nbOfCells=getNumberOfCells();
6016 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6017 arr->alloc(nbOfCells,1);
6018 double *pt=arr->getPointer();
6019 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6020 const int *conn=_nodal_connec->getConstPointer();
6021 const int *connI=_nodal_connec_index->getConstPointer();
6022 const double *coo=_coords->getConstPointer();
6024 for(int i=0;i<nbOfCells;i++,pt++)
6026 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6029 case INTERP_KERNEL::NORM_TRI3:
6031 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6032 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6035 case INTERP_KERNEL::NORM_QUAD4:
6037 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6038 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6041 case INTERP_KERNEL::NORM_TETRA4:
6043 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6044 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6048 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6050 conn+=connI[i+1]-connI[i];
6052 ret->setName("AspectRatio");
6053 ret->synchronizeTimeWithSupport();
6058 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6059 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6060 * treated: INTERP_KERNEL::NORM_QUAD4.
6061 * For a cell of other type an exception is thrown.
6062 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6063 * cells and one time, lying on \a this mesh. The caller is to delete this
6064 * field using decrRef() as it is no more needed.
6065 * \throw If the coordinates array is not set.
6066 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6067 * \throw If the connectivity data array has more than one component.
6068 * \throw If the connectivity data array has a named component.
6069 * \throw If the connectivity index data array has more than one component.
6070 * \throw If the connectivity index data array has a named component.
6071 * \throw If \a this->getMeshDimension() != 2.
6072 * \throw If \a this->getSpaceDimension() != 3.
6073 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6075 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6078 int spaceDim=getSpaceDimension();
6079 int meshDim=getMeshDimension();
6081 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6083 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6084 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6086 int nbOfCells=getNumberOfCells();
6087 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6088 arr->alloc(nbOfCells,1);
6089 double *pt=arr->getPointer();
6090 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6091 const int *conn=_nodal_connec->getConstPointer();
6092 const int *connI=_nodal_connec_index->getConstPointer();
6093 const double *coo=_coords->getConstPointer();
6095 for(int i=0;i<nbOfCells;i++,pt++)
6097 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6100 case INTERP_KERNEL::NORM_QUAD4:
6102 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6103 *pt=INTERP_KERNEL::quadWarp(tmp);
6107 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6109 conn+=connI[i+1]-connI[i];
6111 ret->setName("Warp");
6112 ret->synchronizeTimeWithSupport();
6118 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6119 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6120 * treated: INTERP_KERNEL::NORM_QUAD4.
6121 * For a cell of other type an exception is thrown.
6122 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6123 * cells and one time, lying on \a this mesh. The caller is to delete this
6124 * field using decrRef() as it is no more needed.
6125 * \throw If the coordinates array is not set.
6126 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6127 * \throw If the connectivity data array has more than one component.
6128 * \throw If the connectivity data array has a named component.
6129 * \throw If the connectivity index data array has more than one component.
6130 * \throw If the connectivity index data array has a named component.
6131 * \throw If \a this->getMeshDimension() != 2.
6132 * \throw If \a this->getSpaceDimension() != 3.
6133 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6135 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6138 int spaceDim=getSpaceDimension();
6139 int meshDim=getMeshDimension();
6141 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6143 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6144 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6146 int nbOfCells=getNumberOfCells();
6147 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6148 arr->alloc(nbOfCells,1);
6149 double *pt=arr->getPointer();
6150 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6151 const int *conn=_nodal_connec->getConstPointer();
6152 const int *connI=_nodal_connec_index->getConstPointer();
6153 const double *coo=_coords->getConstPointer();
6155 for(int i=0;i<nbOfCells;i++,pt++)
6157 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6160 case INTERP_KERNEL::NORM_QUAD4:
6162 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6163 *pt=INTERP_KERNEL::quadSkew(tmp);
6167 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6169 conn+=connI[i+1]-connI[i];
6171 ret->setName("Skew");
6172 ret->synchronizeTimeWithSupport();
6177 * This method aggregate the bbox of each cell and put it into bbox parameter.
6179 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6181 * \throw If \a this is not fully set (coordinates and connectivity).
6182 * \throw If a cell in \a this has no valid nodeId.
6184 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6186 checkFullyDefined();
6187 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6188 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6189 double *bbox(ret->getPointer());
6190 for(int i=0;i<nbOfCells*spaceDim;i++)
6192 bbox[2*i]=std::numeric_limits<double>::max();
6193 bbox[2*i+1]=-std::numeric_limits<double>::max();
6195 const double *coordsPtr(_coords->getConstPointer());
6196 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6197 for(int i=0;i<nbOfCells;i++)
6199 int offset=connI[i]+1;
6200 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6201 for(int j=0;j<nbOfNodesForCell;j++)
6203 int nodeId=conn[offset+j];
6204 if(nodeId>=0 && nodeId<nbOfNodes)
6206 for(int k=0;k<spaceDim;k++)
6208 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6209 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6216 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6217 throw INTERP_KERNEL::Exception(oss.str().c_str());
6225 namespace ParaMEDMEMImpl
6230 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6231 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6240 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6241 bool operator() (const int& pos) { return _conn[pos]==_val; }
6251 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6252 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6253 * \a this is composed in cell types.
6254 * The returned array is of size 3*n where n is the number of different types present in \a this.
6255 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6256 * This parameter is kept only for compatibility with other methode listed above.
6258 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6260 checkConnectivityFullyDefined();
6261 const int *conn=_nodal_connec->getConstPointer();
6262 const int *connI=_nodal_connec_index->getConstPointer();
6263 const int *work=connI;
6264 int nbOfCells=getNumberOfCells();
6265 std::size_t n=getAllTypes().size();
6266 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6267 std::set<INTERP_KERNEL::NormalizedCellType> types;
6268 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6270 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6271 if(types.find(typ)!=types.end())
6273 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6274 oss << " is not contiguous !";
6275 throw INTERP_KERNEL::Exception(oss.str().c_str());
6279 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6280 ret[3*i+1]=(int)std::distance(work,work2);
6287 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6288 * only for types cell, type node is not managed.
6289 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6290 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6291 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6292 * If 2 or more same geometric type is in \a code and exception is thrown too.
6294 * This method firstly checks
6295 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6296 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6297 * an exception is thrown too.
6299 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6300 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6301 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6303 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6306 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6307 std::size_t sz=code.size();
6310 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6311 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6313 bool isNoPflUsed=true;
6314 for(std::size_t i=0;i<n;i++)
6315 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6317 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6319 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6320 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6321 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6324 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6327 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6328 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6329 if(types.size()==_types.size())
6332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6334 int *retPtr=ret->getPointer();
6335 const int *connI=_nodal_connec_index->getConstPointer();
6336 const int *conn=_nodal_connec->getConstPointer();
6337 int nbOfCells=getNumberOfCells();
6340 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6342 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6343 int offset=(int)std::distance(connI,i);
6344 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6345 int nbOfCellsOfCurType=(int)std::distance(i,j);
6346 if(code[3*kk+2]==-1)
6347 for(int k=0;k<nbOfCellsOfCurType;k++)
6351 int idInIdsPerType=code[3*kk+2];
6352 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6354 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6357 zePfl->checkAllocated();
6358 if(zePfl->getNumberOfComponents()==1)
6360 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6362 if(*k>=0 && *k<nbOfCellsOfCurType)
6363 *retPtr=(*k)+offset;
6366 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6367 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6368 throw INTERP_KERNEL::Exception(oss.str().c_str());
6373 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6376 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6380 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6381 oss << " should be in [0," << idsPerType.size() << ") !";
6382 throw INTERP_KERNEL::Exception(oss.str().c_str());
6391 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6392 * 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.
6393 * 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.
6394 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6396 * \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.
6397 * \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,
6398 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6399 * \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.
6400 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6401 * \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
6403 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6406 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6407 if(profile->getNumberOfComponents()!=1)
6408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6409 checkConnectivityFullyDefined();
6410 const int *conn=_nodal_connec->getConstPointer();
6411 const int *connI=_nodal_connec_index->getConstPointer();
6412 int nbOfCells=getNumberOfCells();
6413 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6414 std::vector<int> typeRangeVals(1);
6415 for(const int *i=connI;i!=connI+nbOfCells;)
6417 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6418 if(std::find(types.begin(),types.end(),curType)!=types.end())
6420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6422 types.push_back(curType);
6423 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6424 typeRangeVals.push_back((int)std::distance(connI,i));
6427 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6428 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6433 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6434 code.resize(3*nbOfCastsFinal);
6435 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6436 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6437 for(int i=0;i<nbOfCastsFinal;i++)
6439 int castId=castsPresent->getIJ(i,0);
6440 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6441 idsInPflPerType2.push_back(tmp3);
6442 code[3*i]=(int)types[castId];
6443 code[3*i+1]=tmp3->getNumberOfTuples();
6444 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6445 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6447 tmp4->copyStringInfoFrom(*profile);
6448 idsPerType2.push_back(tmp4);
6449 code[3*i+2]=(int)idsPerType2.size()-1;
6456 std::size_t sz2=idsInPflPerType2.size();
6457 idsInPflPerType.resize(sz2);
6458 for(std::size_t i=0;i<sz2;i++)
6460 DataArrayInt *locDa=idsInPflPerType2[i];
6462 idsInPflPerType[i]=locDa;
6464 std::size_t sz=idsPerType2.size();
6465 idsPerType.resize(sz);
6466 for(std::size_t i=0;i<sz;i++)
6468 DataArrayInt *locDa=idsPerType2[i];
6470 idsPerType[i]=locDa;
6475 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6476 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6477 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6478 * 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.
6480 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6482 checkFullyDefined();
6483 nM1LevMesh->checkFullyDefined();
6484 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6485 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6486 if(_coords!=nM1LevMesh->getCoords())
6487 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6489 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6490 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6491 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6492 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6493 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6494 tmp->setConnectivity(tmp0,tmp1);
6495 tmp->renumberCells(ret0->getConstPointer(),false);
6496 revDesc=tmp->getNodalConnectivity();
6497 revDescIndx=tmp->getNodalConnectivityIndex();
6498 DataArrayInt *ret=0;
6499 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6502 ret->getMaxValue(tmp2);
6504 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6505 throw INTERP_KERNEL::Exception(oss.str().c_str());
6510 revDescIndx->incrRef();
6513 meshnM1Old2New=ret0;
6518 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6519 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6520 * in "Old to New" mode.
6521 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6522 * this array using decrRef() as it is no more needed.
6523 * \throw If the nodal connectivity of cells is not defined.
6525 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6527 checkConnectivityFullyDefined();
6528 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6529 renumberCells(ret->getConstPointer(),false);
6534 * This methods checks that cells are sorted by their types.
6535 * This method makes asumption (no check) that connectivity is correctly set before calling.
6537 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6539 checkFullyDefined();
6540 const int *conn=_nodal_connec->getConstPointer();
6541 const int *connI=_nodal_connec_index->getConstPointer();
6542 int nbOfCells=getNumberOfCells();
6543 std::set<INTERP_KERNEL::NormalizedCellType> types;
6544 for(const int *i=connI;i!=connI+nbOfCells;)
6546 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6547 if(types.find(curType)!=types.end())
6549 types.insert(curType);
6550 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6556 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6557 * The geometric type order is specified by MED file.
6559 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6561 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6563 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6567 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6568 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6569 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6570 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6572 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6574 checkFullyDefined();
6575 const int *conn=_nodal_connec->getConstPointer();
6576 const int *connI=_nodal_connec_index->getConstPointer();
6577 int nbOfCells=getNumberOfCells();
6581 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6582 for(const int *i=connI;i!=connI+nbOfCells;)
6584 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6585 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6586 if(isTypeExists!=orderEnd)
6588 int pos=(int)std::distance(orderBg,isTypeExists);
6592 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6596 if(sg.find(curType)==sg.end())
6598 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6609 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6610 * 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
6611 * 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'.
6613 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6615 checkConnectivityFullyDefined();
6616 int nbOfCells=getNumberOfCells();
6617 const int *conn=_nodal_connec->getConstPointer();
6618 const int *connI=_nodal_connec_index->getConstPointer();
6619 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6620 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6621 tmpa->alloc(nbOfCells,1);
6622 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6623 tmpb->fillWithZero();
6624 int *tmp=tmpa->getPointer();
6625 int *tmp2=tmpb->getPointer();
6626 for(const int *i=connI;i!=connI+nbOfCells;i++)
6628 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6631 int pos=(int)std::distance(orderBg,where);
6633 tmp[std::distance(connI,i)]=pos;
6637 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6638 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6639 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6640 throw INTERP_KERNEL::Exception(oss.str().c_str());
6643 nbPerType=tmpb.retn();
6648 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6650 * \return a new object containing the old to new correspondance.
6652 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6654 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6656 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6660 * 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.
6661 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6662 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6663 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6665 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6667 DataArrayInt *nbPerType=0;
6668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6669 nbPerType->decrRef();
6670 return tmpa->buildPermArrPerLevel();
6674 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6675 * The number of cells remains unchanged after the call of this method.
6676 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6677 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6679 * \return the array giving the correspondance old to new.
6681 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6683 checkFullyDefined();
6685 const int *conn=_nodal_connec->getConstPointer();
6686 const int *connI=_nodal_connec_index->getConstPointer();
6687 int nbOfCells=getNumberOfCells();
6688 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6689 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6690 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6692 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6693 types.push_back(curType);
6694 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6696 DataArrayInt *ret=DataArrayInt::New();
6697 ret->alloc(nbOfCells,1);
6698 int *retPtr=ret->getPointer();
6699 std::fill(retPtr,retPtr+nbOfCells,-1);
6701 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6703 for(const int *i=connI;i!=connI+nbOfCells;i++)
6704 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6705 retPtr[std::distance(connI,i)]=newCellId++;
6707 renumberCells(retPtr,false);
6712 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6713 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6714 * This method makes asumption that connectivity is correctly set before calling.
6716 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6718 checkConnectivityFullyDefined();
6719 const int *conn=_nodal_connec->getConstPointer();
6720 const int *connI=_nodal_connec_index->getConstPointer();
6721 int nbOfCells=getNumberOfCells();
6722 std::vector<MEDCouplingUMesh *> ret;
6723 for(const int *i=connI;i!=connI+nbOfCells;)
6725 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6726 int beginCellId=(int)std::distance(connI,i);
6727 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6728 int endCellId=(int)std::distance(connI,i);
6729 int sz=endCellId-beginCellId;
6730 int *cells=new int[sz];
6731 for(int j=0;j<sz;j++)
6732 cells[j]=beginCellId+j;
6733 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6741 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6742 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6743 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6745 * \return a newly allocated instance, that the caller must manage.
6746 * \throw If \a this contains more than one geometric type.
6747 * \throw If the nodal connectivity of \a this is not fully defined.
6748 * \throw If the internal data is not coherent.
6750 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6752 checkConnectivityFullyDefined();
6753 if(_types.size()!=1)
6754 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6755 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6756 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6757 ret->setCoords(getCoords());
6758 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6762 retC->setNodalConnectivity(c);
6766 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6768 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6769 DataArrayInt *c=0,*ci=0;
6770 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6771 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6772 retD->setNodalConnectivity(cs,cis);
6777 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6779 checkConnectivityFullyDefined();
6780 if(_types.size()!=1)
6781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6782 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6783 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6786 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6787 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6788 throw INTERP_KERNEL::Exception(oss.str().c_str());
6790 int nbCells=getNumberOfCells();
6792 int nbNodesPerCell=(int)cm.getNumberOfNodes();
6793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6794 int *outPtr=connOut->getPointer();
6795 const int *conn=_nodal_connec->begin();
6796 const int *connI=_nodal_connec_index->begin();
6798 for(int i=0;i<nbCells;i++,connI++)
6800 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6801 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6804 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 << ") !";
6805 throw INTERP_KERNEL::Exception(oss.str().c_str());
6808 return connOut.retn();
6811 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6813 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6814 checkConnectivityFullyDefined();
6815 if(_types.size()!=1)
6816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6817 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6819 throw INTERP_KERNEL::Exception(msg0);
6820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6821 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6822 int *cp(c->getPointer()),*cip(ci->getPointer());
6823 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6825 for(int i=0;i<nbCells;i++,cip++,incip++)
6827 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6828 int delta(stop-strt);
6831 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6832 cp=std::copy(incp+strt,incp+stop,cp);
6834 throw INTERP_KERNEL::Exception(msg0);
6837 throw INTERP_KERNEL::Exception(msg0);
6838 cip[1]=cip[0]+delta;
6840 nodalConn=c.retn(); nodalConnIndex=ci.retn();
6844 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6845 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6846 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6847 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6848 * are not used here to avoid the build of big permutation array.
6850 * \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
6851 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6852 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6853 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6854 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6855 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6856 * \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
6857 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6859 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6860 DataArrayInt *&szOfCellGrpOfSameType,
6861 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6863 std::vector<const MEDCouplingUMesh *> ms2;
6864 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6867 (*it)->checkConnectivityFullyDefined();
6871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6872 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6873 int meshDim=ms2[0]->getMeshDimension();
6874 std::vector<const MEDCouplingUMesh *> m1ssm;
6875 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6877 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6878 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6881 ret1->alloc(0,1); ret2->alloc(0,1);
6882 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6884 if(meshDim!=(*it)->getMeshDimension())
6885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6886 if(refCoo!=(*it)->getCoords())
6887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6888 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6889 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6890 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6891 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6893 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6894 m1ssmSingleAuto.push_back(singleCell);
6895 m1ssmSingle.push_back(singleCell);
6896 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6899 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6900 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6901 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6902 for(std::size_t i=0;i<m1ssm.size();i++)
6903 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6904 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6905 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6906 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6911 * This method returns a newly created DataArrayInt instance.
6912 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6914 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6916 checkFullyDefined();
6917 const int *conn=_nodal_connec->getConstPointer();
6918 const int *connIndex=_nodal_connec_index->getConstPointer();
6919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6920 for(const int *w=begin;w!=end;w++)
6921 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6922 ret->pushBackSilent(*w);
6927 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6928 * are in [0:getNumberOfCells())
6930 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6932 checkFullyDefined();
6933 const int *conn=_nodal_connec->getConstPointer();
6934 const int *connI=_nodal_connec_index->getConstPointer();
6935 int nbOfCells=getNumberOfCells();
6936 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6937 int *tmp=new int[nbOfCells];
6938 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6941 for(const int *i=connI;i!=connI+nbOfCells;i++)
6942 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6943 tmp[std::distance(connI,i)]=j++;
6945 DataArrayInt *ret=DataArrayInt::New();
6946 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6947 ret->copyStringInfoFrom(*da);
6948 int *retPtr=ret->getPointer();
6949 const int *daPtr=da->getConstPointer();
6950 int nbOfElems=da->getNbOfElems();
6951 for(int k=0;k<nbOfElems;k++)
6952 retPtr[k]=tmp[daPtr[k]];
6958 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6959 * This method \b works \b for mesh sorted by type.
6960 * cells whose ids is in 'idsPerGeoType' array.
6961 * This method conserves coords and name of mesh.
6963 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6965 std::vector<int> code=getDistributionOfTypes();
6966 std::size_t nOfTypesInThis=code.size()/3;
6967 int sz=0,szOfType=0;
6968 for(std::size_t i=0;i<nOfTypesInThis;i++)
6973 szOfType=code[3*i+1];
6975 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6976 if(*work<0 || *work>=szOfType)
6978 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6979 oss << ". It should be in [0," << szOfType << ") !";
6980 throw INTERP_KERNEL::Exception(oss.str().c_str());
6982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6983 int *idsPtr=idsTokeep->getPointer();
6985 for(std::size_t i=0;i<nOfTypesInThis;i++)
6988 for(int j=0;j<code[3*i+1];j++)
6991 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6992 offset+=code[3*i+1];
6994 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6995 ret->copyTinyInfoFrom(this);
7000 * This method returns a vector of size 'this->getNumberOfCells()'.
7001 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7003 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7005 int ncell=getNumberOfCells();
7006 std::vector<bool> ret(ncell);
7007 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7008 const int *c=getNodalConnectivity()->getConstPointer();
7009 for(int i=0;i<ncell;i++)
7011 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7012 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7013 ret[i]=cm.isQuadratic();
7019 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7021 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7023 if(other->getType()!=UNSTRUCTURED)
7024 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7025 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7026 return MergeUMeshes(this,otherC);
7030 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7031 * computed by averaging coordinates of cell nodes, so this method is not a right
7032 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7033 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7034 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7035 * components. The caller is to delete this array using decrRef() as it is
7037 * \throw If the coordinates array is not set.
7038 * \throw If the nodal connectivity of cells is not defined.
7039 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7041 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7043 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7044 int spaceDim=getSpaceDimension();
7045 int nbOfCells=getNumberOfCells();
7046 ret->alloc(nbOfCells,spaceDim);
7047 ret->copyStringInfoFrom(*getCoords());
7048 double *ptToFill=ret->getPointer();
7049 const int *nodal=_nodal_connec->getConstPointer();
7050 const int *nodalI=_nodal_connec_index->getConstPointer();
7051 const double *coor=_coords->getConstPointer();
7052 for(int i=0;i<nbOfCells;i++)
7054 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7055 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7062 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7063 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7065 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7066 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7068 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7069 * \throw If \a this is not fully defined (coordinates and connectivity)
7070 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7072 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7074 checkFullyDefined();
7075 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7076 int spaceDim=getSpaceDimension();
7077 int nbOfCells=getNumberOfCells();
7078 int nbOfNodes=getNumberOfNodes();
7079 ret->alloc(nbOfCells,spaceDim);
7080 double *ptToFill=ret->getPointer();
7081 const int *nodal=_nodal_connec->getConstPointer();
7082 const int *nodalI=_nodal_connec_index->getConstPointer();
7083 const double *coor=_coords->getConstPointer();
7084 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7086 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7087 std::fill(ptToFill,ptToFill+spaceDim,0.);
7088 if(type!=INTERP_KERNEL::NORM_POLYHED)
7090 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7092 if(*conn>=0 && *conn<nbOfNodes)
7093 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7096 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7097 throw INTERP_KERNEL::Exception(oss.str().c_str());
7100 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7101 if(nbOfNodesInCell>0)
7102 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7105 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7106 throw INTERP_KERNEL::Exception(oss.str().c_str());
7111 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7113 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7115 if(*it>=0 && *it<nbOfNodes)
7116 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7119 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7120 throw INTERP_KERNEL::Exception(oss.str().c_str());
7124 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7127 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7128 throw INTERP_KERNEL::Exception(oss.str().c_str());
7136 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7137 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7138 * are specified via an array of cell ids.
7139 * \warning Validity of the specified cell ids is not checked!
7140 * Valid range is [ 0, \a this->getNumberOfCells() ).
7141 * \param [in] begin - an array of cell ids of interest.
7142 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7143 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7144 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7145 * caller is to delete this array using decrRef() as it is no more needed.
7146 * \throw If the coordinates array is not set.
7147 * \throw If the nodal connectivity of cells is not defined.
7149 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7150 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7152 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7154 DataArrayDouble *ret=DataArrayDouble::New();
7155 int spaceDim=getSpaceDimension();
7156 int nbOfTuple=(int)std::distance(begin,end);
7157 ret->alloc(nbOfTuple,spaceDim);
7158 double *ptToFill=ret->getPointer();
7159 double *tmp=new double[spaceDim];
7160 const int *nodal=_nodal_connec->getConstPointer();
7161 const int *nodalI=_nodal_connec_index->getConstPointer();
7162 const double *coor=_coords->getConstPointer();
7163 for(const int *w=begin;w!=end;w++)
7165 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7166 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7174 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7177 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7180 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7181 da->checkAllocated();
7182 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7184 int nbOfTuples=da->getNumberOfTuples();
7185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7187 c->alloc(2*nbOfTuples,1);
7188 cI->alloc(nbOfTuples+1,1);
7189 int *cp=c->getPointer();
7190 int *cip=cI->getPointer();
7192 for(int i=0;i<nbOfTuples;i++)
7194 *cp++=INTERP_KERNEL::NORM_POINT1;
7198 ret->setConnectivity(c,cI,true);
7202 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7203 * Cells and nodes of
7204 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7205 * \param [in] mesh1 - the first mesh.
7206 * \param [in] mesh2 - the second mesh.
7207 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7208 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7209 * is no more needed.
7210 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7211 * \throw If the coordinates array is not set in none of the meshes.
7212 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7213 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7215 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7217 std::vector<const MEDCouplingUMesh *> tmp(2);
7218 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7219 return MergeUMeshes(tmp);
7223 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7224 * Cells and nodes of
7225 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7226 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7227 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7228 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7229 * is no more needed.
7230 * \throw If \a a.size() == 0.
7231 * \throw If \a a[ *i* ] == NULL.
7232 * \throw If the coordinates array is not set in none of the meshes.
7233 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7234 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7236 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7238 std::size_t sz=a.size();
7240 return MergeUMeshesLL(a);
7241 for(std::size_t ii=0;ii<sz;ii++)
7244 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7245 throw INTERP_KERNEL::Exception(oss.str().c_str());
7247 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7248 std::vector< const MEDCouplingUMesh * > aa(sz);
7250 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7252 const MEDCouplingUMesh *cur=a[i];
7253 const DataArrayDouble *coo=cur->getCoords();
7255 spaceDim=coo->getNumberOfComponents();
7258 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7259 for(std::size_t i=0;i<sz;i++)
7261 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7264 return MergeUMeshesLL(aa);
7269 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7272 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7273 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7274 int meshDim=(*it)->getMeshDimension();
7275 int nbOfCells=(*it)->getNumberOfCells();
7276 int meshLgth=(*it++)->getMeshLength();
7277 for(;it!=a.end();it++)
7279 if(meshDim!=(*it)->getMeshDimension())
7280 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7281 nbOfCells+=(*it)->getNumberOfCells();
7282 meshLgth+=(*it)->getMeshLength();
7284 std::vector<const MEDCouplingPointSet *> aps(a.size());
7285 std::copy(a.begin(),a.end(),aps.begin());
7286 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7287 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7288 ret->setCoords(pts);
7289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7290 c->alloc(meshLgth,1);
7291 int *cPtr=c->getPointer();
7292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7293 cI->alloc(nbOfCells+1,1);
7294 int *cIPtr=cI->getPointer();
7298 for(it=a.begin();it!=a.end();it++)
7300 int curNbOfCell=(*it)->getNumberOfCells();
7301 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7302 const int *curC=(*it)->_nodal_connec->getConstPointer();
7303 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7304 for(int j=0;j<curNbOfCell;j++)
7306 const int *src=curC+curCI[j];
7308 for(;src!=curC+curCI[j+1];src++,cPtr++)
7316 offset+=curCI[curNbOfCell];
7317 offset2+=(*it)->getNumberOfNodes();
7320 ret->setConnectivity(c,cI,true);
7327 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7328 * dimension and sharing the node coordinates array.
7329 * All cells of the first mesh precede all cells of the second mesh
7330 * within the result mesh.
7331 * \param [in] mesh1 - the first mesh.
7332 * \param [in] mesh2 - the second mesh.
7333 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7334 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7335 * is no more needed.
7336 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7337 * \throw If the meshes do not share the node coordinates array.
7338 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7339 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7341 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7343 std::vector<const MEDCouplingUMesh *> tmp(2);
7344 tmp[0]=mesh1; tmp[1]=mesh2;
7345 return MergeUMeshesOnSameCoords(tmp);
7349 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7350 * dimension and sharing the node coordinates array.
7351 * All cells of the *i*-th mesh precede all cells of the
7352 * (*i*+1)-th mesh within the result mesh.
7353 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7354 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7355 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7356 * is no more needed.
7357 * \throw If \a a.size() == 0.
7358 * \throw If \a a[ *i* ] == NULL.
7359 * \throw If the meshes do not share the node coordinates array.
7360 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7361 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7363 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7366 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7367 for(std::size_t ii=0;ii<meshes.size();ii++)
7370 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7371 throw INTERP_KERNEL::Exception(oss.str().c_str());
7373 const DataArrayDouble *coords=meshes.front()->getCoords();
7374 int meshDim=meshes.front()->getMeshDimension();
7375 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7377 int meshIndexLgth=0;
7378 for(;iter!=meshes.end();iter++)
7380 if(coords!=(*iter)->getCoords())
7381 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7382 if(meshDim!=(*iter)->getMeshDimension())
7383 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7384 meshLgth+=(*iter)->getMeshLength();
7385 meshIndexLgth+=(*iter)->getNumberOfCells();
7387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7388 nodal->alloc(meshLgth,1);
7389 int *nodalPtr=nodal->getPointer();
7390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7391 nodalIndex->alloc(meshIndexLgth+1,1);
7392 int *nodalIndexPtr=nodalIndex->getPointer();
7394 for(iter=meshes.begin();iter!=meshes.end();iter++)
7396 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7397 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7398 int nbOfCells=(*iter)->getNumberOfCells();
7399 int meshLgth2=(*iter)->getMeshLength();
7400 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7401 if(iter!=meshes.begin())
7402 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7404 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7407 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7408 ret->setName("merge");
7409 ret->setMeshDimension(meshDim);
7410 ret->setConnectivity(nodal,nodalIndex,true);
7411 ret->setCoords(coords);
7416 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7417 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7418 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7419 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7420 * New" mode are returned for each input mesh.
7421 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7422 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7423 * valid values [0,1,2], see zipConnectivityTraducer().
7424 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7425 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7426 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7428 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7429 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7430 * is no more needed.
7431 * \throw If \a meshes.size() == 0.
7432 * \throw If \a meshes[ *i* ] == NULL.
7433 * \throw If the meshes do not share the node coordinates array.
7434 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7435 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7436 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7437 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7439 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7441 //All checks are delegated to MergeUMeshesOnSameCoords
7442 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7443 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7444 corr.resize(meshes.size());
7445 std::size_t nbOfMeshes=meshes.size();
7447 const int *o2nPtr=o2n->getConstPointer();
7448 for(std::size_t i=0;i<nbOfMeshes;i++)
7450 DataArrayInt *tmp=DataArrayInt::New();
7451 int curNbOfCells=meshes[i]->getNumberOfCells();
7452 tmp->alloc(curNbOfCells,1);
7453 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7454 offset+=curNbOfCells;
7455 tmp->setName(meshes[i]->getName().c_str());
7462 * Makes all given meshes share the nodal connectivity array. The common connectivity
7463 * array is created by concatenating the connectivity arrays of all given meshes. All
7464 * the given meshes must be of the same space dimension but dimension of cells **can
7465 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7466 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7467 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7468 * \param [in,out] meshes - a vector of meshes to update.
7469 * \throw If any of \a meshes is NULL.
7470 * \throw If the coordinates array is not set in any of \a meshes.
7471 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7472 * \throw If \a meshes are of different space dimension.
7474 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7476 std::size_t sz=meshes.size();
7479 std::vector< const DataArrayDouble * > coords(meshes.size());
7480 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7481 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7485 (*it)->checkConnectivityFullyDefined();
7486 const DataArrayDouble *coo=(*it)->getCoords();
7491 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7492 oss << " has no coordinate array defined !";
7493 throw INTERP_KERNEL::Exception(oss.str().c_str());
7498 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7499 oss << " is null !";
7500 throw INTERP_KERNEL::Exception(oss.str().c_str());
7503 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7504 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7505 int offset=(*it)->getNumberOfNodes();
7506 (*it++)->setCoords(res);
7507 for(;it!=meshes.end();it++)
7509 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7510 (*it)->setCoords(res);
7511 (*it)->shiftNodeNumbersInConn(offset);
7512 offset+=oldNumberOfNodes;
7517 * Merges nodes coincident with a given precision within all given meshes that share
7518 * the nodal connectivity array. The given meshes **can be of different** mesh
7519 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7520 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7521 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7522 * \param [in,out] meshes - a vector of meshes to update.
7523 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7524 * \throw If any of \a meshes is NULL.
7525 * \throw If the \a meshes do not share the same node coordinates array.
7526 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7528 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7532 std::set<const DataArrayDouble *> s;
7533 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7536 s.insert((*it)->getCoords());
7539 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 !";
7540 throw INTERP_KERNEL::Exception(oss.str().c_str());
7545 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 !";
7546 throw INTERP_KERNEL::Exception(oss.str().c_str());
7548 const DataArrayDouble *coo=*(s.begin());
7552 DataArrayInt *comm,*commI;
7553 coo->findCommonTuples(eps,-1,comm,commI);
7554 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7555 int oldNbOfNodes=coo->getNumberOfTuples();
7557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7558 if(oldNbOfNodes==newNbOfNodes)
7560 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7561 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7563 (*it)->renumberNodesInConn(o2n->getConstPointer());
7564 (*it)->setCoords(newCoords);
7569 * 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.
7570 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7571 * \param isQuad specifies the policy of connectivity.
7572 * @ret in/out parameter in which the result will be append
7574 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7576 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7577 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7578 ret.push_back(cm.getExtrudedType());
7579 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7582 case INTERP_KERNEL::NORM_POINT1:
7584 ret.push_back(connBg[1]);
7585 ret.push_back(connBg[1]+nbOfNodesPerLev);
7588 case INTERP_KERNEL::NORM_SEG2:
7590 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7591 ret.insert(ret.end(),conn,conn+4);
7594 case INTERP_KERNEL::NORM_SEG3:
7596 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7597 ret.insert(ret.end(),conn,conn+8);
7600 case INTERP_KERNEL::NORM_QUAD4:
7602 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7603 ret.insert(ret.end(),conn,conn+8);
7606 case INTERP_KERNEL::NORM_TRI3:
7608 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7609 ret.insert(ret.end(),conn,conn+6);
7612 case INTERP_KERNEL::NORM_TRI6:
7614 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,
7615 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7616 ret.insert(ret.end(),conn,conn+15);
7619 case INTERP_KERNEL::NORM_QUAD8:
7622 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7623 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7624 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7626 ret.insert(ret.end(),conn,conn+20);
7629 case INTERP_KERNEL::NORM_POLYGON:
7631 std::back_insert_iterator< std::vector<int> > ii(ret);
7632 std::copy(connBg+1,connEnd,ii);
7634 std::reverse_iterator<const int *> rConnBg(connEnd);
7635 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7636 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7637 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7638 for(std::size_t i=0;i<nbOfRadFaces;i++)
7641 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7642 std::copy(conn,conn+4,ii);
7647 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7652 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7654 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7656 double v[3]={0.,0.,0.};
7657 std::size_t sz=std::distance(begin,end);
7660 for(std::size_t i=0;i<sz;i++)
7662 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];
7663 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7664 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7666 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7670 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7672 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7674 std::vector<std::pair<int,int> > edges;
7675 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7676 const int *bgFace=begin;
7677 for(std::size_t i=0;i<nbOfFaces;i++)
7679 const int *endFace=std::find(bgFace+1,end,-1);
7680 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7681 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7683 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7684 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7686 edges.push_back(p1);
7690 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7694 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7696 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7698 double vec0[3],vec1[3];
7699 std::size_t sz=std::distance(begin,end);
7701 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7702 int nbOfNodes=(int)sz/2;
7703 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7704 const double *pt0=coords+3*begin[0];
7705 const double *pt1=coords+3*begin[nbOfNodes];
7706 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7707 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7710 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7712 std::size_t sz=std::distance(begin,end);
7713 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7714 std::size_t nbOfNodes(sz/2);
7715 std::copy(begin,end,(int *)tmp);
7716 for(std::size_t j=1;j<nbOfNodes;j++)
7718 begin[j]=tmp[nbOfNodes-j];
7719 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7723 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7725 std::size_t sz=std::distance(begin,end);
7727 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7728 double vec0[3],vec1[3];
7729 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7730 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];
7731 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;
7734 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7736 std::size_t sz=std::distance(begin,end);
7738 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7740 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7741 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7742 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7746 * 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 )
7747 * 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
7750 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7751 * \param [in] coords the coordinates with nb of components exactly equal to 3
7752 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7753 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7754 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7756 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7758 int nbFaces=std::count(begin+1,end,-1)+1;
7759 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7760 double *vPtr=v->getPointer();
7761 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7762 double *pPtr=p->getPointer();
7763 const int *stFaceConn=begin+1;
7764 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7766 const int *endFaceConn=std::find(stFaceConn,end,-1);
7767 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7768 stFaceConn=endFaceConn+1;
7770 pPtr=p->getPointer(); vPtr=v->getPointer();
7771 DataArrayInt *comm1=0,*commI1=0;
7772 v->findCommonTuples(eps,-1,comm1,commI1);
7773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7774 const int *comm1Ptr=comm1->getConstPointer();
7775 const int *commI1Ptr=commI1->getConstPointer();
7776 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7777 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7779 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7780 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7781 mm->finishInsertingCells();
7783 for(int i=0;i<nbOfGrps1;i++)
7785 int vecId=comm1Ptr[commI1Ptr[i]];
7786 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7787 DataArrayInt *comm2=0,*commI2=0;
7788 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7789 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7790 const int *comm2Ptr=comm2->getConstPointer();
7791 const int *commI2Ptr=commI2->getConstPointer();
7792 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7793 for(int j=0;j<nbOfGrps2;j++)
7795 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7797 res->insertAtTheEnd(begin,end);
7798 res->pushBackSilent(-1);
7802 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7804 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7805 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7806 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7807 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7810 const int *idsNodePtr=idsNode->getConstPointer();
7811 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];
7812 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7813 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7814 if(std::abs(norm)>eps)
7816 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7817 mm3->rotate(center,vec,angle);
7819 mm3->changeSpaceDimension(2);
7820 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7821 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7822 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7823 int nbOfCells=mm4->getNumberOfCells();
7824 for(int k=0;k<nbOfCells;k++)
7827 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7828 res->pushBackSilent(idsNodePtr[*work]);
7829 res->pushBackSilent(-1);
7834 res->popBackSilent();
7838 * 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
7839 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7841 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7842 * \param [in] coords coordinates expected to have 3 components.
7843 * \param [in] begin start of the nodal connectivity of the face.
7844 * \param [in] end end of the nodal connectivity (excluded) of the face.
7845 * \param [out] v the normalized vector of size 3
7846 * \param [out] p the pos of plane
7848 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7850 std::size_t nbPoints=std::distance(begin,end);
7852 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7853 double vec[3]={0.,0.,0.};
7855 bool refFound=false;
7856 for(;j<nbPoints-1 && !refFound;j++)
7858 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7859 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7860 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7861 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7865 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7868 for(std::size_t i=j;i<nbPoints-1;i++)
7871 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7872 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7873 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7874 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7877 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7878 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];
7879 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7882 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7883 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7887 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7891 * This method tries to obtain a well oriented polyhedron.
7892 * If the algorithm fails, an exception will be thrown.
7894 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7896 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7897 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7898 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7900 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7901 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7902 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7904 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7907 std::size_t smthChanged=0;
7908 for(std::size_t i=0;i<nbOfFaces;i++)
7910 endFace=std::find(bgFace+1,end,-1);
7911 nbOfEdgesInFace=std::distance(bgFace,endFace);
7915 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7917 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7918 std::pair<int,int> p2(p1.second,p1.first);
7919 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7920 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7921 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7926 std::reverse(bgFace+1,endFace);
7927 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7929 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7930 std::pair<int,int> p2(p1.second,p1.first);
7931 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7932 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7933 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7934 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7935 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7936 if(it!=edgesOK.end())
7939 edgesFinished.push_back(p1);
7942 edgesOK.push_back(p1);
7949 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7951 if(!edgesOK.empty())
7952 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7953 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7954 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7956 for(std::size_t i=0;i<nbOfFaces;i++)
7958 endFace=std::find(bgFace+1,end,-1);
7959 std::reverse(bgFace+1,endFace);
7966 * This method makes the assumption spacedimension == meshdimension == 2.
7967 * This method works only for linear cells.
7969 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7971 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7973 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7974 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7975 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7977 int nbOfNodesExpected=m->getNumberOfNodes();
7978 if(m->getNumberOfCells()!=nbOfNodesExpected)
7979 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7980 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7981 const int *n2oPtr=n2o->getConstPointer();
7982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7983 m->getReverseNodalConnectivity(revNodal,revNodalI);
7984 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7985 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7986 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7988 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7989 if(nbOfNodesExpected<1)
7992 int prevNode=nodalPtr[nodalIPtr[0]+1];
7993 *work++=n2oPtr[prevNode];
7994 for(int i=1;i<nbOfNodesExpected;i++)
7996 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7998 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7999 conn.erase(prevNode);
8002 int curNode=*(conn.begin());
8003 *work++=n2oPtr[curNode];
8004 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8005 shar.erase(prevCell);
8008 prevCell=*(shar.begin());
8012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8015 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8024 * This method makes the assumption spacedimension == meshdimension == 3.
8025 * This method works only for linear cells.
8027 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8029 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8031 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8032 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8033 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8034 const int *conn=m->getNodalConnectivity()->getConstPointer();
8035 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8036 int nbOfCells=m->getNumberOfCells();
8037 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8038 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8041 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8042 for(int i=1;i<nbOfCells;i++)
8045 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8051 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8052 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8054 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8058 for(int i=0;i<nbOfNodesInCell;i++)
8059 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8060 else if(spaceDim==2)
8062 for(int i=0;i<nbOfNodesInCell;i++)
8064 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8069 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8072 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8074 int nbOfCells=getNumberOfCells();
8076 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8077 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};
8078 ofs << " <" << getVTKDataSetType() << ">\n";
8079 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8080 ofs << " <PointData>\n" << pointData << std::endl;
8081 ofs << " </PointData>\n";
8082 ofs << " <CellData>\n" << cellData << std::endl;
8083 ofs << " </CellData>\n";
8084 ofs << " <Points>\n";
8085 if(getSpaceDimension()==3)
8086 _coords->writeVTK(ofs,8,"Points");
8089 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8090 coo->writeVTK(ofs,8,"Points");
8092 ofs << " </Points>\n";
8093 ofs << " <Cells>\n";
8094 const int *cPtr=_nodal_connec->getConstPointer();
8095 const int *cIPtr=_nodal_connec_index->getConstPointer();
8096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8099 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8100 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8101 int szFaceOffsets=0,szConn=0;
8102 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8105 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8108 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8109 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8113 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8114 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8115 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8116 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8117 w4=std::copy(c.begin(),c.end(),w4);
8120 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8121 types->writeVTK(ofs,8,"UInt8","types");
8122 offsets->writeVTK(ofs,8,"Int32","offsets");
8123 if(szFaceOffsets!=0)
8124 {//presence of Polyhedra
8125 connectivity->reAlloc(szConn);
8126 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8128 w1=faces->getPointer();
8129 for(int i=0;i<nbOfCells;i++)
8130 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8132 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8134 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8135 for(int j=0;j<nbFaces;j++)
8137 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8138 *w1++=(int)std::distance(w6,w5);
8139 w1=std::copy(w6,w5,w1);
8143 faces->writeVTK(ofs,8,"Int32","faces");
8145 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8146 ofs << " </Cells>\n";
8147 ofs << " </Piece>\n";
8148 ofs << " </" << getVTKDataSetType() << ">\n";
8151 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8153 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8155 { stream << " Not set !"; return ; }
8156 stream << " Mesh dimension : " << _mesh_dim << ".";
8160 { stream << " No coordinates set !"; return ; }
8161 if(!_coords->isAllocated())
8162 { stream << " Coordinates set but not allocated !"; return ; }
8163 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8164 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8165 if(!_nodal_connec_index)
8166 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8167 if(!_nodal_connec_index->isAllocated())
8168 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8169 int lgth=_nodal_connec_index->getNumberOfTuples();
8170 int cpt=_nodal_connec_index->getNumberOfComponents();
8171 if(cpt!=1 || lgth<1)
8173 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8176 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8178 return std::string("UnstructuredGrid");
8182 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8183 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8184 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8186 * \param [in] m1 - the first input mesh which is a partitioned object.
8187 * \param [in] m2 - the second input mesh which is a partition tool.
8188 * \param [in] eps - precision used to detect coincident mesh entities.
8189 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8190 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8191 * this array using decrRef() as it is no more needed.
8192 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8193 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8194 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8195 * any cell of \a m2. The caller is to delete this array using decrRef() as
8196 * it is no more needed.
8197 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8198 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8199 * is no more needed.
8200 * \throw If the coordinates array is not set in any of the meshes.
8201 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8202 * \throw If any of the meshes is not a 2D mesh in 2D space.
8204 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8206 m1->checkFullyDefined();
8207 m2->checkFullyDefined();
8208 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8209 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8210 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8211 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8212 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8213 std::vector<double> addCoo,addCoordsQuadratic;
8214 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8215 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8216 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8217 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8218 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8220 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8221 std::vector< std::vector<int> > intersectEdge2;
8222 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8223 subDiv2.clear(); dd5=0; dd6=0;
8224 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8225 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8226 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8227 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8229 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8230 addCooDa->alloc((int)(addCoo.size())/2,2);
8231 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8232 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8233 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8234 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8235 std::vector<const DataArrayDouble *> coordss(4);
8236 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8237 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8238 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8243 ret->setConnectivity(conn,connI,true);
8244 ret->setCoords(coo);
8245 cellNb1=c1.retn(); cellNb2=c2.retn();
8249 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8250 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8251 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8252 const std::vector<double>& addCoords,
8253 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8255 static const int SPACEDIM=2;
8256 const double *coo1=m1->getCoords()->getConstPointer();
8257 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8258 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8259 int offset1=m1->getNumberOfNodes();
8260 const double *coo2=m2->getCoords()->getConstPointer();
8261 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8262 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8263 int offset2=offset1+m2->getNumberOfNodes();
8264 int offset3=offset2+((int)addCoords.size())/2;
8265 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8266 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8267 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8268 int ncell1=m1->getNumberOfCells();
8270 for(int i=0;i<ncell1;i++)
8272 std::vector<int> candidates2;
8273 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8274 std::map<INTERP_KERNEL::Node *,int> mapp;
8275 std::map<int,INTERP_KERNEL::Node *> mappRev;
8276 INTERP_KERNEL::QuadraticPolygon pol1;
8277 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8278 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8279 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8280 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8281 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8283 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
8284 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8285 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8286 for(it1.first();!it1.finished();it1.next())
8287 edges1.insert(it1.current()->getPtr());
8289 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8290 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8292 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8294 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8295 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8296 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8297 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8298 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8301 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8303 pol1.initLocationsWithOther(pol2s[ii]);
8304 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8305 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8306 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8312 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8314 catch(INTERP_KERNEL::Exception& e)
8316 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();
8317 throw INTERP_KERNEL::Exception(oss.str().c_str());
8320 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8321 (*it).second->decrRef();
8326 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8329 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8330 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8331 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8332 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8333 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8335 static const int SPACEDIM=2;
8336 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8337 desc2=DataArrayInt::New();
8338 descIndx2=DataArrayInt::New();
8339 revDesc2=DataArrayInt::New();
8340 revDescIndx2=DataArrayInt::New();
8341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8343 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8344 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8346 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8347 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8348 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8349 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8350 int ncell1=m1Desc->getNumberOfCells();
8351 int ncell2=m2Desc->getNumberOfCells();
8352 intersectEdge1.resize(ncell1);
8353 colinear2.resize(ncell2);
8354 subDiv2.resize(ncell2);
8355 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8356 std::vector<int> candidates1(1);
8357 int offset1=m1->getNumberOfNodes();
8358 int offset2=offset1+m2->getNumberOfNodes();
8359 for(int i=0;i<ncell1;i++)
8361 std::vector<int> candidates2;
8362 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8363 if(!candidates2.empty())
8365 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8366 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8368 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8369 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8374 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8376 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8377 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8381 * This method performs the 2nd step of Partition of 2D mesh.
8382 * This method has 4 inputs :
8383 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8384 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8385 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8386 * 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'
8387 * \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'
8388 * \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.
8389 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8391 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)
8393 int offset1=m1->getNumberOfNodes();
8394 int ncell=m2->getNumberOfCells();
8395 const int *c=m2->getNodalConnectivity()->getConstPointer();
8396 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8397 const double *coo=m2->getCoords()->getConstPointer();
8398 const double *cooBis=m1->getCoords()->getConstPointer();
8399 int offset2=offset1+m2->getNumberOfNodes();
8400 intersectEdge.resize(ncell);
8401 for(int i=0;i<ncell;i++,cI++)
8403 const std::vector<int>& divs=subDiv[i];
8404 int nnode=cI[1]-cI[0]-1;
8405 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8406 std::map<INTERP_KERNEL::Node *, int> mapp22;
8407 for(int j=0;j<nnode;j++)
8409 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8410 int nnid=c[(*cI)+j+1];
8411 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8412 mapp22[nn]=nnid+offset1;
8414 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8415 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8416 ((*it).second.first)->decrRef();
8417 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8418 std::map<INTERP_KERNEL::Node *,int> mapp3;
8419 for(std::size_t j=0;j<divs.size();j++)
8422 INTERP_KERNEL::Node *tmp=0;
8424 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8426 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8428 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8432 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8433 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8440 * 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).
8441 * 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
8442 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8443 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8444 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8445 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8446 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8447 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8448 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8449 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8450 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8451 * \param [out] cut3DSuf input/output param.
8453 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8454 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8455 const int *desc, const int *descIndx,
8456 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8458 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8459 int nbOf3DSurfCell=(int)cut3DSurf.size();
8460 for(int i=0;i<nbOf3DSurfCell;i++)
8462 std::vector<int> res;
8463 int offset=descIndx[i];
8464 int nbOfSeg=descIndx[i+1]-offset;
8465 for(int j=0;j<nbOfSeg;j++)
8467 int edgeId=desc[offset+j];
8468 int status=cut3DCurve[edgeId];
8472 res.push_back(status);
8475 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8476 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8484 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8490 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8491 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8494 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8498 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8503 {// case when plane is on a multi colinear edge of a polyhedron
8504 if((int)res.size()==2*nbOfSeg)
8506 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8509 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8516 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8517 * 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).
8518 * 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
8519 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8520 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8521 * \param desc is the descending connectivity 3D->3DSurf
8522 * \param descIndx is the descending connectivity index 3D->3DSurf
8524 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8525 const int *desc, const int *descIndx,
8526 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8528 checkFullyDefined();
8529 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8531 const int *nodal3D=_nodal_connec->getConstPointer();
8532 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8533 int nbOfCells=getNumberOfCells();
8534 for(int i=0;i<nbOfCells;i++)
8536 std::map<int, std::set<int> > m;
8537 int offset=descIndx[i];
8538 int nbOfFaces=descIndx[i+1]-offset;
8541 for(int j=0;j<nbOfFaces;j++)
8543 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8544 if(p.first!=-1 && p.second!=-1)
8548 start=p.first; end=p.second;
8549 m[p.first].insert(p.second);
8550 m[p.second].insert(p.first);
8554 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8555 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8556 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8557 INTERP_KERNEL::NormalizedCellType cmsId;
8558 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8559 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8560 for(unsigned k=0;k<nbOfNodesSon;k++)
8562 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8563 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8570 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8574 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8575 const std::set<int>& s=(*it).second;
8576 std::set<int> s2; s2.insert(prev);
8578 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8581 int val=*s3.begin();
8582 conn.push_back(start);
8589 conn.push_back(end);
8592 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8593 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8594 cellIds->pushBackSilent(i);
8600 * 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
8601 * 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
8602 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8603 * 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
8604 * 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.
8606 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8608 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8610 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8613 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8614 if(cm.getDimension()==2)
8616 const int *node=nodalConnBg+1;
8617 int startNode=*node++;
8618 double refX=coords[2*startNode];
8619 for(;node!=nodalConnEnd;node++)
8621 if(coords[2*(*node)]<refX)
8624 refX=coords[2*startNode];
8627 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8631 double angle0=-M_PI/2;
8636 double angleNext=0.;
8637 while(nextNode!=startNode)
8641 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8643 if(*node!=tmpOut.back() && *node!=prevNode)
8645 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8646 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8651 res=angle0-angleM+2.*M_PI;
8660 if(nextNode!=startNode)
8662 angle0=angleNext-M_PI;
8665 prevNode=tmpOut.back();
8666 tmpOut.push_back(nextNode);
8669 std::vector<int> tmp3(2*(sz-1));
8670 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8671 std::copy(nodalConnBg+1,nodalConnEnd,it);
8672 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8674 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8677 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8679 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8684 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8685 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8690 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8693 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8697 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8698 * 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.
8700 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8701 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8702 * \param [in,out] arr array in which the remove operation will be done.
8703 * \param [in,out] arrIndx array in the remove operation will modify
8704 * \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])
8705 * \return true if \b arr and \b arrIndx have been modified, false if not.
8707 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8709 if(!arrIndx || !arr)
8710 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8711 if(offsetForRemoval<0)
8712 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8713 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8714 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8715 int *arrIPtr=arrIndx->getPointer();
8718 const int *arrPtr=arr->getConstPointer();
8719 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8720 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8722 if(*arrIPtr-previousArrI>offsetForRemoval)
8724 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8726 if(s.find(*work)==s.end())
8727 arrOut.push_back(*work);
8730 previousArrI=*arrIPtr;
8731 *arrIPtr=(int)arrOut.size();
8733 if(arr->getNumberOfTuples()==(int)arrOut.size())
8735 arr->alloc((int)arrOut.size(),1);
8736 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8741 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8742 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8743 * The selection of extraction is done standardly in new2old format.
8744 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8746 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8747 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8748 * \param [in] arrIn arr origin array from which the extraction will be done.
8749 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8750 * \param [out] arrOut the resulting array
8751 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8752 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8754 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8755 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8757 if(!arrIn || !arrIndxIn)
8758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8759 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8760 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8761 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8762 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8763 const int *arrInPtr=arrIn->getConstPointer();
8764 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8765 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8767 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8768 int maxSizeOfArr=arrIn->getNumberOfTuples();
8769 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8770 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8771 arrIo->alloc((int)(sz+1),1);
8772 const int *idsIt=idsOfSelectBg;
8773 int *work=arrIo->getPointer();
8776 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8778 if(*idsIt>=0 && *idsIt<nbOfGrps)
8779 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8782 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8783 throw INTERP_KERNEL::Exception(oss.str().c_str());
8789 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8790 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8791 throw INTERP_KERNEL::Exception(oss.str().c_str());
8794 arro->alloc(lgth,1);
8795 work=arro->getPointer();
8796 idsIt=idsOfSelectBg;
8797 for(std::size_t i=0;i<sz;i++,idsIt++)
8799 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8800 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8803 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8804 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8805 throw INTERP_KERNEL::Exception(oss.str().c_str());
8809 arrIndexOut=arrIo.retn();
8813 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8814 * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
8815 * The selection of extraction is done standardly in new2old format.
8816 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8818 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8819 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8820 * \param [in] arrIn arr origin array from which the extraction will be done.
8821 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8822 * \param [out] arrOut the resulting array
8823 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8824 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8826 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8827 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8829 if(!arrIn || !arrIndxIn)
8830 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8831 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8832 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8833 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8834 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8835 const int *arrInPtr=arrIn->getConstPointer();
8836 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8837 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8840 int maxSizeOfArr=arrIn->getNumberOfTuples();
8841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8843 arrIo->alloc((int)(sz+1),1);
8844 int idsIt=idsOfSelectStart;
8845 int *work=arrIo->getPointer();
8848 for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8850 if(idsIt>=0 && idsIt<nbOfGrps)
8851 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8854 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8855 throw INTERP_KERNEL::Exception(oss.str().c_str());
8861 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8862 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8863 throw INTERP_KERNEL::Exception(oss.str().c_str());
8866 arro->alloc(lgth,1);
8867 work=arro->getPointer();
8868 idsIt=idsOfSelectStart;
8869 for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8871 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8872 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8875 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8876 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8877 throw INTERP_KERNEL::Exception(oss.str().c_str());
8881 arrIndexOut=arrIo.retn();
8885 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8886 * 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
8887 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8888 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8890 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8891 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8892 * \param [in] arrIn arr origin array from which the extraction will be done.
8893 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8894 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8895 * \param [in] srcArrIndex index array of \b srcArr
8896 * \param [out] arrOut the resulting array
8897 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8899 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8901 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8902 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8903 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8905 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8906 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8909 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8910 std::vector<bool> v(nbOfTuples,true);
8912 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8913 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8914 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8916 if(*it>=0 && *it<nbOfTuples)
8919 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8923 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8924 throw INTERP_KERNEL::Exception(oss.str().c_str());
8927 srcArrIndexPtr=srcArrIndex->getConstPointer();
8928 arrIo->alloc(nbOfTuples+1,1);
8929 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8930 const int *arrInPtr=arrIn->getConstPointer();
8931 const int *srcArrPtr=srcArr->getConstPointer();
8932 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8933 int *arroPtr=arro->getPointer();
8934 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8938 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8939 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8943 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8944 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8945 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8949 arrIndexOut=arrIo.retn();
8953 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8954 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8956 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8957 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8958 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8959 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8960 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8961 * \param [in] srcArrIndex index array of \b srcArr
8963 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8965 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8966 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8968 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8969 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8970 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8971 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8972 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8973 int *arrInOutPtr=arrInOut->getPointer();
8974 const int *srcArrPtr=srcArr->getConstPointer();
8975 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8977 if(*it>=0 && *it<nbOfTuples)
8979 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8980 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8983 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] !";
8984 throw INTERP_KERNEL::Exception(oss.str().c_str());
8989 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8990 throw INTERP_KERNEL::Exception(oss.str().c_str());
8996 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8997 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8998 * 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]].
8999 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9000 * A negative value in \b arrIn means that it is ignored.
9001 * 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.
9003 * \param [in] arrIn arr origin array from which the extraction will be done.
9004 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9005 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9006 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9008 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9010 int seed=0,nbOfDepthPeelingPerformed=0;
9011 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9015 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9016 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9017 * 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]].
9018 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9019 * A negative value in \b arrIn means that it is ignored.
9020 * 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.
9021 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9022 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9023 * \param [in] arrIn arr origin array from which the extraction will be done.
9024 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9025 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9026 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9027 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9028 * \sa MEDCouplingUMesh::partitionBySpreadZone
9030 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9032 nbOfDepthPeelingPerformed=0;
9034 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9035 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9038 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9042 std::vector<bool> fetched(nbOfTuples,false);
9043 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9046 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)
9048 nbOfDepthPeelingPerformed=0;
9049 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9051 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9052 std::vector<bool> fetched2(nbOfTuples,false);
9054 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9056 if(*seedElt>=0 && *seedElt<nbOfTuples)
9057 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9059 { 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()); }
9061 const int *arrInPtr=arrIn->getConstPointer();
9062 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9063 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9064 std::vector<int> idsToFetch1(seedBg,seedEnd);
9065 std::vector<int> idsToFetch2;
9066 std::vector<int> *idsToFetch=&idsToFetch1;
9067 std::vector<int> *idsToFetchOther=&idsToFetch2;
9068 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9070 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9071 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9073 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9074 std::swap(idsToFetch,idsToFetchOther);
9075 idsToFetchOther->clear();
9076 nbOfDepthPeelingPerformed++;
9078 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9080 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9081 int *retPtr=ret->getPointer();
9082 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9089 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9090 * 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
9091 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9092 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9094 * \param [in] start begin of set of ids of the input extraction (included)
9095 * \param [in] end end of set of ids of the input extraction (excluded)
9096 * \param [in] step step of the set of ids in range mode.
9097 * \param [in] arrIn arr origin array from which the extraction will be done.
9098 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9099 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9100 * \param [in] srcArrIndex index array of \b srcArr
9101 * \param [out] arrOut the resulting array
9102 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9104 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9106 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9107 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9108 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9110 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9114 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9116 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9117 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9118 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9120 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9122 if(it>=0 && it<nbOfTuples)
9123 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9126 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9127 throw INTERP_KERNEL::Exception(oss.str().c_str());
9130 srcArrIndexPtr=srcArrIndex->getConstPointer();
9131 arrIo->alloc(nbOfTuples+1,1);
9132 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9133 const int *arrInPtr=arrIn->getConstPointer();
9134 const int *srcArrPtr=srcArr->getConstPointer();
9135 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9136 int *arroPtr=arro->getPointer();
9137 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9139 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9142 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9143 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9147 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9148 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9152 arrIndexOut=arrIo.retn();
9156 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9157 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9159 * \param [in] start begin of set of ids of the input extraction (included)
9160 * \param [in] end end of set of ids of the input extraction (excluded)
9161 * \param [in] step step of the set of ids in range mode.
9162 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9163 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9164 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9165 * \param [in] srcArrIndex index array of \b srcArr
9167 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9169 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9170 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9172 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9173 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9174 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9175 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9176 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9177 int *arrInOutPtr=arrInOut->getPointer();
9178 const int *srcArrPtr=srcArr->getConstPointer();
9179 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9181 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9183 if(it>=0 && it<nbOfTuples)
9185 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9186 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9189 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9190 throw INTERP_KERNEL::Exception(oss.str().c_str());
9195 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9196 throw INTERP_KERNEL::Exception(oss.str().c_str());
9202 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9203 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9204 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9205 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9206 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9208 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9210 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9212 checkFullyDefined();
9213 int mdim=getMeshDimension();
9214 int spaceDim=getSpaceDimension();
9216 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9217 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9218 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9219 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9220 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9221 ret->setCoords(getCoords());
9222 ret->allocateCells((int)partition.size());
9224 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9226 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9231 cell=tmp->buildUnionOf2DMesh();
9234 cell=tmp->buildUnionOf3DMesh();
9237 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9240 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9243 ret->finishInsertingCells();
9248 * This method partitions \b this into contiguous zone.
9249 * This method only needs a well defined connectivity. Coordinates are not considered here.
9250 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9252 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9254 int nbOfCellsCur=getNumberOfCells();
9255 std::vector<DataArrayInt *> ret;
9258 DataArrayInt *neigh=0,*neighI=0;
9259 computeNeighborsOfCells(neigh,neighI);
9260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9261 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9262 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9264 while(seed<nbOfCellsCur)
9266 int nbOfPeelPerformed=0;
9267 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9268 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9270 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9271 ret.push_back((*it).retn());
9276 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9277 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9279 * \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.
9280 * \return a newly allocated DataArrayInt to be managed by the caller.
9281 * \throw In case of \a code has not the right format (typically of size 3*n)
9283 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9286 std::size_t nb=code.size()/3;
9287 if(code.size()%3!=0)
9288 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9289 ret->alloc((int)nb,2);
9290 int *retPtr=ret->getPointer();
9291 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9293 retPtr[0]=code[3*i+2];
9294 retPtr[1]=code[3*i+2]+code[3*i+1];
9300 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9301 * All cells in \a this are expected to be linear 3D cells.
9302 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9303 * It leads to an increase to number of cells.
9304 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9305 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9306 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9308 * \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.
9309 * For all other cells, the splitting policy will be ignored.
9310 * \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.
9311 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9312 * an id of old cell producing it. The caller is to delete this array using
9313 * decrRef() as it is no more needed.
9314 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9316 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9317 * \throw If \a this is not fully constituted with linear 3D cells.
9318 * \sa MEDCouplingUMesh::simplexize
9320 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
9322 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9323 checkConnectivityFullyDefined();
9324 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9326 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9327 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9329 int *retPt(ret->getPointer());
9330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9331 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9332 const int *oldc(_nodal_connec->begin());
9333 const int *oldci(_nodal_connec_index->begin());
9334 const double *coords(_coords->begin());
9335 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9337 std::vector<int> a; std::vector<double> b;
9338 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9339 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9340 const int *aa(&a[0]);
9343 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9345 *it=(-(*(it))-1+nbNodes);
9346 addPts->insertAtTheEnd(b.begin(),b.end());
9347 nbNodes+=(int)b.size()/3;
9349 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9350 newConn->insertAtTheEnd(aa,aa+4);
9352 if(!addPts->empty())
9354 addPts->rearrange(3);
9355 nbOfAdditionalPoints=addPts->getNumberOfTuples();
9356 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9357 ret0->setCoords(addPts);
9361 nbOfAdditionalPoints=0;
9362 ret0->setCoords(getCoords());
9364 ret0->setNodalConnectivity(newConn);
9366 ret->computeOffsets2();
9367 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9371 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9372 _own_cell(true),_cell_id(-1),_nb_cell(0)
9377 _nb_cell=mesh->getNumberOfCells();
9381 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9389 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9390 _own_cell(false),_cell_id(bg-1),
9397 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9400 if(_cell_id<_nb_cell)
9409 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9415 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9417 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9420 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9426 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9434 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9440 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9445 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9450 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9452 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9455 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9460 _nb_cell=mesh->getNumberOfCells();
9464 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9471 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9473 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9474 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9475 if(_cell_id<_nb_cell)
9477 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9478 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9479 int startId=_cell_id;
9480 _cell_id+=nbOfElems;
9481 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9487 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9491 _conn=mesh->getNodalConnectivity()->getPointer();
9492 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9496 void MEDCouplingUMeshCell::next()
9498 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9503 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9506 std::string MEDCouplingUMeshCell::repr() const
9508 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9510 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9512 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9516 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9519 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9521 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9522 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9524 return INTERP_KERNEL::NORM_ERROR;
9527 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9530 if(_conn_lgth!=NOTICABLE_FIRST_VAL)