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 "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
50 using namespace ParaMEDMEM;
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54 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 };
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
58 return new MEDCouplingUMesh;
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
63 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64 ret->setName(meshName);
65 ret->setMeshDimension(meshDim);
70 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71 * between \a this and the new mesh.
72 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73 * delete this mesh using decrRef() as it is no more needed.
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
81 * Returns a new MEDCouplingMesh which is a copy of \a this one.
82 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83 * this mesh are shared by the new mesh.
84 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85 * delete this mesh using decrRef() as it is no more needed.
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
89 return new MEDCouplingUMesh(*this,recDeepCpy);
93 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94 * The coordinates are shared between \a this and the returned instance.
96 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97 * \sa MEDCouplingUMesh::deepCpy
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
101 checkConnectivityFullyDefined();
102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104 ret->setConnectivity(c,ci);
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
121 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
127 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
129 ret.push_back(_nodal_connec);
130 if(_nodal_connec_index)
131 ret.push_back(_nodal_connec_index);
135 void MEDCouplingUMesh::updateTime() const
137 MEDCouplingPointSet::updateTime();
140 updateTimeWith(*_nodal_connec);
142 if(_nodal_connec_index)
144 updateTimeWith(*_nodal_connec_index);
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
153 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154 * then \a this mesh is most probably is writable, exchangeable and available for most
155 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156 * this method to check that all is in order with \a this mesh.
157 * \throw If the mesh dimension is not set.
158 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
159 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160 * \throw If the connectivity data array has more than one component.
161 * \throw If the connectivity data array has a named component.
162 * \throw If the connectivity index data array has more than one component.
163 * \throw If the connectivity index data array has a named component.
165 void MEDCouplingUMesh::checkCoherency() const
168 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
170 MEDCouplingPointSet::checkCoherency();
171 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
173 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
175 std::ostringstream message;
176 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177 throw INTERP_KERNEL::Exception(message.str().c_str());
182 if(_nodal_connec->getNumberOfComponents()!=1)
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184 if(_nodal_connec->getInfoOnComponent(0)!="")
185 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190 if(_nodal_connec_index)
192 if(_nodal_connec_index->getNumberOfComponents()!=1)
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194 if(_nodal_connec_index->getInfoOnComponent(0)!="")
195 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204 * then \a this mesh is most probably is writable, exchangeable and available for all
205 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206 * method thoroughly checks the nodal connectivity.
207 * \param [in] eps - a not used parameter.
208 * \throw If the mesh dimension is not set.
209 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
210 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211 * \throw If the connectivity data array has more than one component.
212 * \throw If the connectivity data array has a named component.
213 * \throw If the connectivity index data array has more than one component.
214 * \throw If the connectivity index data array has a named component.
215 * \throw If number of nodes defining an element does not correspond to the type of element.
216 * \throw If the nodal connectivity includes an invalid node id.
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
223 int meshDim=getMeshDimension();
224 int nbOfNodes=getNumberOfNodes();
225 int nbOfCells=getNumberOfCells();
226 const int *ptr=_nodal_connec->getConstPointer();
227 const int *ptrI=_nodal_connec_index->getConstPointer();
228 for(int i=0;i<nbOfCells;i++)
230 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231 if((int)cm.getDimension()!=meshDim)
233 std::ostringstream oss;
234 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235 throw INTERP_KERNEL::Exception(oss.str().c_str());
237 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
239 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
241 std::ostringstream oss;
242 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
243 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244 throw INTERP_KERNEL::Exception(oss.str().c_str());
246 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
251 if(nodeId>=nbOfNodes)
253 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254 throw INTERP_KERNEL::Exception(oss.str().c_str());
259 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260 throw INTERP_KERNEL::Exception(oss.str().c_str());
264 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
266 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267 throw INTERP_KERNEL::Exception(oss.str().c_str());
276 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277 * then \a this mesh is most probably is writable, exchangeable and available for all
278 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
279 * \param [in] eps - a not used parameter.
280 * \throw If the mesh dimension is not set.
281 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
282 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283 * \throw If the connectivity data array has more than one component.
284 * \throw If the connectivity data array has a named component.
285 * \throw If the connectivity index data array has more than one component.
286 * \throw If the connectivity index data array has a named component.
287 * \throw If number of nodes defining an element does not correspond to the type of element.
288 * \throw If the nodal connectivity includes an invalid node id.
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
292 checkCoherency1(eps);
296 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297 * elements contained in the mesh. For more info on the mesh dimension see
298 * \ref MEDCouplingUMeshPage.
299 * \param [in] meshDim - a new mesh dimension.
300 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
304 if(meshDim<-1 || meshDim>3)
305 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
311 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
315 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
317 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
318 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324 if(_nodal_connec_index)
326 _nodal_connec_index->decrRef();
330 _nodal_connec->decrRef();
332 _nodal_connec_index=DataArrayInt::New();
333 _nodal_connec_index->reserve(nbOfCells+1);
334 _nodal_connec_index->pushBackSilent(0);
335 _nodal_connec=DataArrayInt::New();
336 _nodal_connec->reserve(2*nbOfCells);
342 * Appends a cell to the connectivity array. For deeper understanding what is
343 * happening see \ref MEDCouplingUMeshNodalConnectivity.
344 * \param [in] type - type of cell to add.
345 * \param [in] size - number of nodes constituting this cell.
346 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
348 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
349 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
351 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
353 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
354 if(_nodal_connec_index==0)
355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
356 if((int)cm.getDimension()==_mesh_dim)
359 if(size!=(int)cm.getNumberOfNodes())
361 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
362 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
363 throw INTERP_KERNEL::Exception(oss.str().c_str());
365 int idx=_nodal_connec_index->back();
367 _nodal_connec_index->pushBackSilent(val);
368 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
373 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
374 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
375 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
376 throw INTERP_KERNEL::Exception(oss.str().c_str());
381 * Compacts data arrays to release unused memory. This method is to be called after
382 * finishing cell insertion using \a this->insertNextCell().
384 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
385 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
387 void MEDCouplingUMesh::finishInsertingCells()
389 _nodal_connec->pack();
390 _nodal_connec_index->pack();
391 _nodal_connec->declareAsNew();
392 _nodal_connec_index->declareAsNew();
397 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
398 * Useful for python users.
400 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
402 return new MEDCouplingUMeshCellIterator(this);
406 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
407 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
408 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
409 * Useful for python users.
411 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
413 if(!checkConsecutiveCellTypes())
414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
415 return new MEDCouplingUMeshCellByTypeEntry(this);
419 * Returns a set of all cell types available in \a this mesh.
420 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
421 * \warning this method does not throw any exception even if \a this is not defined.
423 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
429 * This method is a method that compares \a this and \a other.
430 * This method compares \b all attributes, even names and component names.
432 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
435 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
436 std::ostringstream oss; oss.precision(15);
437 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
440 reason="mesh given in input is not castable in MEDCouplingUMesh !";
443 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
445 if(_mesh_dim!=otherC->_mesh_dim)
447 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
451 if(_types!=otherC->_types)
453 oss << "umesh geometric type mismatch :\nThis geometric types are :";
454 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
455 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
456 oss << "\nOther geometric types are :";
457 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
458 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
462 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
463 if(_nodal_connec==0 || otherC->_nodal_connec==0)
465 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
468 if(_nodal_connec!=otherC->_nodal_connec)
469 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
471 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
474 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
475 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
477 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
480 if(_nodal_connec_index!=otherC->_nodal_connec_index)
481 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
483 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
490 * Checks if data arrays of this mesh (node coordinates, nodal
491 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
493 * \param [in] other - the mesh to compare with.
494 * \param [in] prec - precision value used to compare node coordinates.
495 * \return bool - \a true if the two meshes are same.
497 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
499 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
502 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
504 if(_mesh_dim!=otherC->_mesh_dim)
506 if(_types!=otherC->_types)
508 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
509 if(_nodal_connec==0 || otherC->_nodal_connec==0)
511 if(_nodal_connec!=otherC->_nodal_connec)
512 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
514 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
515 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
517 if(_nodal_connec_index!=otherC->_nodal_connec_index)
518 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
524 * Checks if \a this and \a other meshes are geometrically equivalent with high
525 * probability, else an exception is thrown. The meshes are considered equivalent if
526 * (1) meshes contain the same number of nodes and the same number of elements of the
527 * same types (2) three cells of the two meshes (first, last and middle) are based
528 * on coincident nodes (with a specified precision).
529 * \param [in] other - the mesh to compare with.
530 * \param [in] prec - the precision used to compare nodes of the two meshes.
531 * \throw If the two meshes do not match.
533 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
535 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
536 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
538 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
542 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
543 * cells each node belongs to.
544 * \warning For speed reasons, this method does not check if node ids in the nodal
545 * connectivity correspond to the size of node coordinates array.
546 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
547 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
548 * dividing cell ids in \a revNodal into groups each referring to one
549 * node. Its every element (except the last one) is an index pointing to the
550 * first id of a group of cells. For example cells sharing the node #1 are
551 * described by following range of indices:
552 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
553 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
554 * Number of cells sharing the *i*-th node is
555 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
556 * \throw If the coordinates array is not set.
557 * \throw If the nodal connectivity of cells is not defined.
559 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
560 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
562 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
565 int nbOfNodes=getNumberOfNodes();
566 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
567 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
568 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
569 const int *conn=_nodal_connec->getConstPointer();
570 const int *connIndex=_nodal_connec_index->getConstPointer();
571 int nbOfCells=getNumberOfCells();
572 int nbOfEltsInRevNodal=0;
573 for(int eltId=0;eltId<nbOfCells;eltId++)
575 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
576 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
577 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
578 if(*iter>=0)//for polyhedrons
580 nbOfEltsInRevNodal++;
581 revNodalIndxPtr[(*iter)+1]++;
584 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
585 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
586 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
587 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
588 for(int eltId=0;eltId<nbOfCells;eltId++)
590 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
591 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
592 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
593 if(*iter>=0)//for polyhedrons
594 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
600 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
605 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
611 if(cm.getOrientationStatus(nb,conn1,conn2))
618 class MinusOneSonsGenerator
621 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
622 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
623 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
624 static const int DELTA=1;
626 const INTERP_KERNEL::CellModel& _cm;
629 class MinusOneSonsGeneratorBiQuadratic
632 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
633 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
634 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
635 static const int DELTA=1;
637 const INTERP_KERNEL::CellModel& _cm;
640 class MinusTwoSonsGenerator
643 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
644 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
645 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
646 static const int DELTA=2;
648 const INTERP_KERNEL::CellModel& _cm;
654 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
655 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
656 * describing correspondence between cells of \a this and the result meshes are
657 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
658 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
659 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
660 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
661 * \warning For speed reasons, this method does not check if node ids in the nodal
662 * connectivity correspond to the size of node coordinates array.
663 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
664 * to write this mesh to the MED file, its cells must be sorted using
665 * sortCellsInMEDFileFrmt().
666 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
667 * each cell of \a this mesh.
668 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
669 * dividing cell ids in \a desc into groups each referring to one
670 * cell of \a this mesh. Its every element (except the last one) is an index
671 * pointing to the first id of a group of cells. For example cells of the
672 * result mesh bounding the cell #1 of \a this mesh are described by following
674 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
675 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
676 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
677 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
678 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
679 * by each cell of the result mesh.
680 * \param [in,out] revDescIndx - the array, of length one more than number of cells
681 * in the result mesh,
682 * dividing cell ids in \a revDesc into groups each referring to one
683 * cell of the result mesh the same way as \a descIndx divides \a desc.
684 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
685 * delete this mesh using decrRef() as it is no more needed.
686 * \throw If the coordinates array is not set.
687 * \throw If the nodal connectivity of cells is node defined.
688 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
689 * revDescIndx == NULL.
691 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
692 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
693 * \sa buildDescendingConnectivity2()
695 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
697 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
701 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
702 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
703 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
704 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
705 * \sa MEDCouplingUMesh::buildDescendingConnectivity
707 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
710 if(getMeshDimension()!=3)
711 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
712 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
716 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
717 * this->getMeshDimension(), that bound cells of \a this mesh. In
718 * addition arrays describing correspondence between cells of \a this and the result
719 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
720 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
721 * mesh. This method differs from buildDescendingConnectivity() in that apart
722 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
723 * result meshes. So a positive id means that order of nodes in corresponding cells
724 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
725 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
726 * i.e. cell ids are one-based.
727 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
728 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
729 * \warning For speed reasons, this method does not check if node ids in the nodal
730 * connectivity correspond to the size of node coordinates array.
731 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
732 * to write this mesh to the MED file, its cells must be sorted using
733 * sortCellsInMEDFileFrmt().
734 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
735 * each cell of \a this mesh.
736 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
737 * dividing cell ids in \a desc into groups each referring to one
738 * cell of \a this mesh. Its every element (except the last one) is an index
739 * pointing to the first id of a group of cells. For example cells of the
740 * result mesh bounding the cell #1 of \a this mesh are described by following
742 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
743 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
744 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
745 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
746 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
747 * by each cell of the result mesh.
748 * \param [in,out] revDescIndx - the array, of length one more than number of cells
749 * in the result mesh,
750 * dividing cell ids in \a revDesc into groups each referring to one
751 * cell of the result mesh the same way as \a descIndx divides \a desc.
752 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
753 * shares the node coordinates array with \a this mesh. The caller is to
754 * delete this mesh using decrRef() as it is no more needed.
755 * \throw If the coordinates array is not set.
756 * \throw If the nodal connectivity of cells is node defined.
757 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
758 * revDescIndx == NULL.
760 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
761 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
762 * \sa buildDescendingConnectivity()
764 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
766 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
770 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
771 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
772 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
773 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
775 * \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
776 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
777 * \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.
779 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
781 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
782 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
785 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
787 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
791 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
792 * 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,
793 * excluding a set of meshdim-1 cells in input descending connectivity.
794 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
795 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
796 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
798 * \param [in] desc descending connectivity array.
799 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
800 * \param [in] revDesc reverse descending connectivity array.
801 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
802 * \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
803 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
804 * \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.
806 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
807 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
809 if(!desc || !descIndx || !revDesc || !revDescIndx)
810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
811 const int *descPtr=desc->getConstPointer();
812 const int *descIPtr=descIndx->getConstPointer();
813 const int *revDescPtr=revDesc->getConstPointer();
814 const int *revDescIPtr=revDescIndx->getConstPointer();
816 int nbCells=descIndx->getNumberOfTuples()-1;
817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
819 int *out1Ptr=out1->getPointer();
821 out0->reserve(desc->getNumberOfTuples());
822 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
824 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
826 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
828 out0->insertAtTheEnd(s.begin(),s.end());
830 *out1Ptr=out0->getNumberOfTuples();
832 neighbors=out0.retn();
833 neighborsIndx=out1.retn();
839 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
840 * For speed reasons no check of this will be done.
842 template<class SonsGenerator>
843 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
845 if(!desc || !descIndx || !revDesc || !revDescIndx)
846 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
847 checkConnectivityFullyDefined();
848 int nbOfCells=getNumberOfCells();
849 int nbOfNodes=getNumberOfNodes();
850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
851 int *revNodalIndxPtr=revNodalIndx->getPointer();
852 const int *conn=_nodal_connec->getConstPointer();
853 const int *connIndex=_nodal_connec_index->getConstPointer();
854 std::string name="Mesh constituent of "; name+=getName();
855 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
856 ret->setCoords(getCoords());
857 ret->allocateCells(2*nbOfCells);
858 descIndx->alloc(nbOfCells+1,1);
859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
860 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
861 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
863 int pos=connIndex[eltId];
864 int posP1=connIndex[eltId+1];
865 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
866 SonsGenerator sg(cm);
867 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
868 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
869 for(unsigned i=0;i<nbOfSons;i++)
871 INTERP_KERNEL::NormalizedCellType cmsId;
872 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
873 for(unsigned k=0;k<nbOfNodesSon;k++)
875 revNodalIndxPtr[tmp[k]+1]++;
876 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
877 revDesc2->pushBackSilent(eltId);
879 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
881 int nbOfCellsM1=ret->getNumberOfCells();
882 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
884 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
885 int *revNodalPtr=revNodal->getPointer();
886 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
887 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
888 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
890 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
891 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
892 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
893 if(*iter>=0)//for polyhedrons
894 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
897 DataArrayInt *commonCells=0,*commonCellsI=0;
898 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
900 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
901 int newNbOfCellsM1=-1;
902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
903 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
904 std::vector<bool> isImpacted(nbOfCellsM1,false);
905 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
906 for(int work2=work[0];work2!=work[1];work2++)
907 isImpacted[commonCellsPtr[work2]]=true;
908 const int *o2nM1Ptr=o2nM1->getConstPointer();
909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
910 const int *n2oM1Ptr=n2oM1->getConstPointer();
911 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
912 ret2->copyTinyInfoFrom(this);
913 desc->alloc(descIndx->back(),1);
914 int *descPtr=desc->getPointer();
915 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
916 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
919 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
922 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
924 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
925 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
928 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
931 revDesc->reserve(newNbOfCellsM1);
932 revDescIndx->alloc(newNbOfCellsM1+1,1);
933 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
934 const int *revDesc2Ptr=revDesc2->getConstPointer();
935 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
937 int oldCellIdM1=n2oM1Ptr[i];
938 if(!isImpacted[oldCellIdM1])
940 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
941 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
945 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
946 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
947 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
955 struct MEDCouplingAccVisit
957 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
958 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
959 int _new_nb_of_nodes;
965 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
966 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
967 * array of cell ids. Pay attention that after conversion all algorithms work slower
968 * with \a this mesh than before conversion. <br> If an exception is thrown during the
969 * conversion due presence of invalid ids in the array of cells to convert, as a
970 * result \a this mesh contains some already converted elements. In this case the 2D
971 * mesh remains valid but 3D mesh becomes \b inconsistent!
972 * \warning This method can significantly modify the order of geometric types in \a this,
973 * hence, to write this mesh to the MED file, its cells must be sorted using
974 * sortCellsInMEDFileFrmt().
975 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
976 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
977 * cellIdsToConvertBg.
978 * \throw If the coordinates array is not set.
979 * \throw If the nodal connectivity of cells is node defined.
980 * \throw If dimension of \a this mesh is not either 2 or 3.
982 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
983 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
985 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
988 int dim=getMeshDimension();
990 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
991 int nbOfCells=getNumberOfCells();
994 const int *connIndex=_nodal_connec_index->getConstPointer();
995 int *conn=_nodal_connec->getPointer();
996 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
998 if(*iter>=0 && *iter<nbOfCells)
1000 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1001 if(!cm.isQuadratic())
1002 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1004 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1008 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1009 oss << " in range [0," << nbOfCells << ") !";
1010 throw INTERP_KERNEL::Exception(oss.str().c_str());
1016 int *connIndex=_nodal_connec_index->getPointer();
1017 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1018 const int *connOld=_nodal_connec->getConstPointer();
1019 int connOldLgth=_nodal_connec->getNbOfElems();
1020 std::vector<int> connNew(connOld,connOld+connOldLgth);
1021 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1023 if(*iter>=0 && *iter<nbOfCells)
1025 int pos=connIndex[*iter];
1026 int posP1=connIndex[(*iter)+1];
1027 int lgthOld=posP1-pos-1;
1028 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1029 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1030 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1031 int *tmp=new int[nbOfFaces*lgthOld];
1033 for(int j=0;j<(int)nbOfFaces;j++)
1035 INTERP_KERNEL::NormalizedCellType type;
1036 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1040 std::size_t newLgth=std::distance(tmp,work)-1;
1041 std::size_t delta=newLgth-lgthOld;
1042 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1043 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1044 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1049 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1050 oss << " in range [0," << nbOfCells << ") !";
1051 throw INTERP_KERNEL::Exception(oss.str().c_str());
1054 _nodal_connec->alloc((int)connNew.size(),1);
1055 int *newConnPtr=_nodal_connec->getPointer();
1056 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1062 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1063 * polyhedrons (if \a this is a 3D mesh).
1064 * \warning As this method is purely for user-friendliness and no optimization is
1065 * done to avoid construction of a useless vector, this method can be costly
1067 * \throw If the coordinates array is not set.
1068 * \throw If the nodal connectivity of cells is node defined.
1069 * \throw If dimension of \a this mesh is not either 2 or 3.
1071 void MEDCouplingUMesh::convertAllToPoly()
1073 int nbOfCells=getNumberOfCells();
1074 std::vector<int> cellIds(nbOfCells);
1075 for(int i=0;i<nbOfCells;i++)
1077 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1081 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1082 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1083 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1084 * base facet of the volume and the second half of nodes describes an opposite facet
1085 * having the same number of nodes as the base one. This method converts such
1086 * connectivity to a valid polyhedral format where connectivity of each facet is
1087 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1088 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1089 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1090 * a correct orientation of the first facet of a polyhedron, else orientation of a
1091 * corrected cell is reverse.<br>
1092 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1093 * it releases the user from boring description of polyhedra connectivity in the valid
1095 * \throw If \a this->getMeshDimension() != 3.
1096 * \throw If \a this->getSpaceDimension() != 3.
1097 * \throw If the nodal connectivity of cells is not defined.
1098 * \throw If the coordinates array is not set.
1099 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1100 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1102 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1103 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1105 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1107 checkFullyDefined();
1108 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1110 int nbOfCells=getNumberOfCells();
1111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1112 newCi->alloc(nbOfCells+1,1);
1113 int *newci=newCi->getPointer();
1114 const int *ci=_nodal_connec_index->getConstPointer();
1115 const int *c=_nodal_connec->getConstPointer();
1117 for(int i=0;i<nbOfCells;i++)
1119 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1120 if(type==INTERP_KERNEL::NORM_POLYHED)
1122 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1124 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1125 throw INTERP_KERNEL::Exception(oss.str().c_str());
1127 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1130 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 !";
1131 throw INTERP_KERNEL::Exception(oss.str().c_str());
1134 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)
1137 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1139 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1140 newC->alloc(newci[nbOfCells],1);
1141 int *newc=newC->getPointer();
1142 for(int i=0;i<nbOfCells;i++)
1144 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1145 if(type==INTERP_KERNEL::NORM_POLYHED)
1147 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1148 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1150 for(std::size_t j=0;j<n1;j++)
1152 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1154 newc[n1+5*j+1]=c[ci[i]+1+j];
1155 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1156 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1157 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1162 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1164 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1165 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1170 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1171 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1172 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1173 * to write this mesh to the MED file, its cells must be sorted using
1174 * sortCellsInMEDFileFrmt().
1175 * \return \c true if at least one cell has been converted, \c false else. In the
1176 * last case the nodal connectivity remains unchanged.
1177 * \throw If the coordinates array is not set.
1178 * \throw If the nodal connectivity of cells is not defined.
1179 * \throw If \a this->getMeshDimension() < 0.
1181 bool MEDCouplingUMesh::unPolyze()
1183 checkFullyDefined();
1184 int mdim=getMeshDimension();
1186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1189 int nbOfCells=getNumberOfCells();
1192 int initMeshLgth=getMeshLength();
1193 int *conn=_nodal_connec->getPointer();
1194 int *index=_nodal_connec_index->getPointer();
1199 for(int i=0;i<nbOfCells;i++)
1201 lgthOfCurCell=index[i+1]-posOfCurCell;
1202 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1203 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1204 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1208 switch(cm.getDimension())
1212 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1213 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1214 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1219 int nbOfFaces,lgthOfPolyhConn;
1220 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1221 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1226 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1230 ret=ret || (newType!=type);
1231 conn[newPos]=newType;
1233 posOfCurCell=index[i+1];
1238 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1239 newPos+=lgthOfCurCell;
1240 posOfCurCell+=lgthOfCurCell;
1244 if(newPos!=initMeshLgth)
1245 _nodal_connec->reAlloc(newPos);
1252 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1253 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1254 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1256 * \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
1259 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1261 checkFullyDefined();
1262 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1263 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1264 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1265 coords->recenterForMaxPrecision(eps);
1267 int nbOfCells=getNumberOfCells();
1268 const int *conn=_nodal_connec->getConstPointer();
1269 const int *index=_nodal_connec_index->getConstPointer();
1270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1271 connINew->alloc(nbOfCells+1,1);
1272 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1275 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1277 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1279 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1283 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1284 *connINewPtr=connNew->getNumberOfTuples();
1287 setConnectivity(connNew,connINew,false);
1291 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1292 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1293 * the format of returned DataArrayInt instance.
1295 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1296 * \sa MEDCouplingUMesh::getNodeIdsInUse
1298 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1300 checkConnectivityFullyDefined();
1301 int nbOfCells=getNumberOfCells();
1302 const int *connIndex=_nodal_connec_index->getConstPointer();
1303 const int *conn=_nodal_connec->getConstPointer();
1304 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1305 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1306 std::vector<bool> retS(maxElt,false);
1307 for(int i=0;i<nbOfCells;i++)
1308 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1312 for(int i=0;i<maxElt;i++)
1315 DataArrayInt *ret=DataArrayInt::New();
1317 int *retPtr=ret->getPointer();
1318 for(int i=0;i<maxElt;i++)
1325 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1326 * \sa MEDCouplingUMesh::getNodeIdsInUse
1328 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1330 int nbOfNodes=(int)nodeIdsInUse.size();
1331 int nbOfCells=getNumberOfCells();
1332 const int *connIndex=_nodal_connec_index->getConstPointer();
1333 const int *conn=_nodal_connec->getConstPointer();
1334 for(int i=0;i<nbOfCells;i++)
1335 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1338 if(conn[j]<nbOfNodes)
1339 nodeIdsInUse[conn[j]]=true;
1342 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1343 throw INTERP_KERNEL::Exception(oss.str().c_str());
1349 * Finds nodes not used in any cell and returns an array giving a new id to every node
1350 * by excluding the unused nodes, for which the array holds -1. The result array is
1351 * a mapping in "Old to New" mode.
1352 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1353 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1354 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1355 * if the node is unused or a new id else. The caller is to delete this
1356 * array using decrRef() as it is no more needed.
1357 * \throw If the coordinates array is not set.
1358 * \throw If the nodal connectivity of cells is not defined.
1359 * \throw If the nodal connectivity includes an invalid id.
1361 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1362 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1363 * \sa computeNodeIdsAlg()
1365 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1368 int nbOfNodes=getNumberOfNodes();
1369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1370 ret->alloc(nbOfNodes,1);
1371 int *traducer=ret->getPointer();
1372 std::fill(traducer,traducer+nbOfNodes,-1);
1373 int nbOfCells=getNumberOfCells();
1374 const int *connIndex=_nodal_connec_index->getConstPointer();
1375 const int *conn=_nodal_connec->getConstPointer();
1376 for(int i=0;i<nbOfCells;i++)
1377 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1380 if(conn[j]<nbOfNodes)
1381 traducer[conn[j]]=1;
1384 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1385 throw INTERP_KERNEL::Exception(oss.str().c_str());
1388 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1389 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1394 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1395 * For each cell in \b this the number of nodes constituting cell is computed.
1396 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1397 * So for pohyhedrons some nodes can be counted several times in the returned result.
1399 * \return a newly allocated array
1400 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1402 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1404 checkConnectivityFullyDefined();
1405 int nbOfCells=getNumberOfCells();
1406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1407 ret->alloc(nbOfCells,1);
1408 int *retPtr=ret->getPointer();
1409 const int *conn=getNodalConnectivity()->getConstPointer();
1410 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1411 for(int i=0;i<nbOfCells;i++,retPtr++)
1413 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1414 *retPtr=connI[i+1]-connI[i]-1;
1416 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1422 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1423 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1425 * \return DataArrayInt * - new object to be deallocated by the caller.
1426 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1428 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1430 checkConnectivityFullyDefined();
1431 int nbOfCells=getNumberOfCells();
1432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1433 ret->alloc(nbOfCells,1);
1434 int *retPtr=ret->getPointer();
1435 const int *conn=getNodalConnectivity()->getConstPointer();
1436 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1437 for(int i=0;i<nbOfCells;i++,retPtr++)
1439 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1440 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1441 *retPtr=(int)s.size();
1445 *retPtr=(int)s.size();
1452 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1453 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1455 * \return a newly allocated array
1457 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1459 checkConnectivityFullyDefined();
1460 int nbOfCells=getNumberOfCells();
1461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1462 ret->alloc(nbOfCells,1);
1463 int *retPtr=ret->getPointer();
1464 const int *conn=getNodalConnectivity()->getConstPointer();
1465 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1466 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1468 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1469 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1475 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1476 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1477 * array mean that the corresponding old node is no more used.
1478 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1479 * this->getNumberOfNodes() before call of this method. The caller is to
1480 * delete this array using decrRef() as it is no more needed.
1481 * \throw If the coordinates array is not set.
1482 * \throw If the nodal connectivity of cells is not defined.
1483 * \throw If the nodal connectivity includes an invalid id.
1485 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1486 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1488 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1490 return MEDCouplingPointSet::zipCoordsTraducer();
1494 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1495 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1497 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1502 return AreCellsEqual0(conn,connI,cell1,cell2);
1504 return AreCellsEqual1(conn,connI,cell1,cell2);
1506 return AreCellsEqual2(conn,connI,cell1,cell2);
1508 return AreCellsEqual3(conn,connI,cell1,cell2);
1510 return AreCellsEqual7(conn,connI,cell1,cell2);
1512 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1516 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1518 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1520 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1521 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1526 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1528 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1530 int sz=connI[cell1+1]-connI[cell1];
1531 if(sz==connI[cell2+1]-connI[cell2])
1533 if(conn[connI[cell1]]==conn[connI[cell2]])
1535 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1536 unsigned dim=cm.getDimension();
1542 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1543 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1544 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1545 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1546 return work!=tmp+sz1?1:0;
1549 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1552 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1559 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1561 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1563 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1565 if(conn[connI[cell1]]==conn[connI[cell2]])
1567 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1568 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1576 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1578 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1580 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1582 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1583 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1590 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1592 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1594 int sz=connI[cell1+1]-connI[cell1];
1595 if(sz==connI[cell2+1]-connI[cell2])
1597 if(conn[connI[cell1]]==conn[connI[cell2]])
1599 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1600 unsigned dim=cm.getDimension();
1606 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1607 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1608 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1609 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1614 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1615 std::reverse_iterator<int *> it2((int *)tmp);
1616 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1622 return work!=tmp+sz1?1:0;
1625 {//case of SEG2 and SEG3
1626 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1628 if(!cm.isQuadratic())
1630 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1631 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1632 if(std::equal(it1,it2,conn+connI[cell2]+1))
1638 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])
1645 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1652 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1653 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1654 * and result remains unchanged.
1655 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1656 * If in 'candidates' pool -1 value is considered as an empty value.
1657 * WARNING this method returns only ONE set of result !
1659 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1661 if(candidates.size()<1)
1664 std::vector<int>::const_iterator iter=candidates.begin();
1665 int start=(*iter++);
1666 for(;iter!=candidates.end();iter++)
1668 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1673 result->pushBackSilent(start);
1677 result->pushBackSilent(*iter);
1679 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1686 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1687 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1689 * \param [in] compType input specifying the technique used to compare cells each other.
1690 * - 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.
1691 * - 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)
1692 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1693 * - 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
1694 * can be used for users not sensitive to orientation of cell
1695 * \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.
1696 * \param [out] commonCells
1697 * \param [out] commonCellsI
1698 * \return the correspondance array old to new in a newly allocated array.
1701 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1703 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1704 getReverseNodalConnectivity(revNodal,revNodalI);
1705 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1708 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1709 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1712 int nbOfCells=nodalI->getNumberOfTuples()-1;
1713 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1714 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1715 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1716 std::vector<bool> isFetched(nbOfCells,false);
1719 for(int i=0;i<nbOfCells;i++)
1723 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1724 std::vector<int> v,v2;
1725 if(connOfNode!=connPtr+connIPtr[i+1])
1727 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1728 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1731 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1735 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1736 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1737 v2.resize(std::distance(v2.begin(),it));
1741 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1743 int pos=commonCellsI->back();
1744 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1745 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1746 isFetched[*it]=true;
1754 for(int i=startCellId;i<nbOfCells;i++)
1758 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1759 std::vector<int> v,v2;
1760 if(connOfNode!=connPtr+connIPtr[i+1])
1762 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1765 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1769 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1770 v2.resize(std::distance(v2.begin(),it));
1774 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1776 int pos=commonCellsI->back();
1777 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1778 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1779 isFetched[*it]=true;
1785 commonCellsArr=commonCells.retn();
1786 commonCellsIArr=commonCellsI.retn();
1790 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1791 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1792 * than \a other->getNumberOfCells() in the returned array means that there is no
1793 * corresponding cell in \a this mesh.
1794 * It is expected that \a this and \a other meshes share the same node coordinates
1795 * array, if it is not so an exception is thrown.
1796 * \param [in] other - the mesh to compare with.
1797 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1798 * valid values [0,1,2], see zipConnectivityTraducer().
1799 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1800 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1801 * values. The caller is to delete this array using
1802 * decrRef() as it is no more needed.
1803 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1806 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1807 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1808 * \sa checkDeepEquivalOnSameNodesWith()
1809 * \sa checkGeoEquivalWith()
1811 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1813 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1814 int nbOfCells=getNumberOfCells();
1815 static const int possibleCompType[]={0,1,2};
1816 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1818 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1819 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1821 throw INTERP_KERNEL::Exception(oss.str().c_str());
1823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1824 arr=o2n->substr(nbOfCells);
1825 arr->setName(other->getName().c_str());
1827 if(other->getNumberOfCells()==0)
1829 return arr->getMaxValue(tmp)<nbOfCells;
1833 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1834 * This method tries to determine if \b other is fully included in \b this.
1835 * The main difference is that this method is not expected to throw exception.
1836 * This method has two outputs :
1838 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1839 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1841 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1843 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1844 DataArrayInt *commonCells=0,*commonCellsI=0;
1845 int thisNbCells=getNumberOfCells();
1846 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1848 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1849 int otherNbCells=other->getNumberOfCells();
1850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1851 arr2->alloc(otherNbCells,1);
1852 arr2->fillWithZero();
1853 int *arr2Ptr=arr2->getPointer();
1854 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1855 for(int i=0;i<nbOfCommon;i++)
1857 int start=commonCellsPtr[commonCellsIPtr[i]];
1858 if(start<thisNbCells)
1860 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1862 int sig=commonCellsPtr[j]>0?1:-1;
1863 int val=std::abs(commonCellsPtr[j])-1;
1864 if(val>=thisNbCells)
1865 arr2Ptr[val-thisNbCells]=sig*(start+1);
1869 arr2->setName(other->getName().c_str());
1870 if(arr2->presenceOfValue(0))
1876 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1880 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1882 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1883 std::vector<const MEDCouplingUMesh *> ms(2);
1886 return MergeUMeshesOnSameCoords(ms);
1890 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1891 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1892 * cellIds is not given explicitely but by a range python like.
1894 * \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.
1895 * \return a newly allocated
1897 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1898 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1900 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1902 if(getMeshDimension()!=-1)
1903 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1906 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1908 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1910 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1912 return const_cast<MEDCouplingUMesh *>(this);
1917 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1918 * The result mesh shares or not the node coordinates array with \a this mesh depending
1919 * on \a keepCoords parameter.
1920 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1921 * to write this mesh to the MED file, its cells must be sorted using
1922 * sortCellsInMEDFileFrmt().
1923 * \param [in] begin - an array of cell ids to include to the new mesh.
1924 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1925 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1926 * array of \a this mesh, else "free" nodes are removed from the result mesh
1927 * by calling zipCoords().
1928 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1929 * to delete this mesh using decrRef() as it is no more needed.
1930 * \throw If the coordinates array is not set.
1931 * \throw If the nodal connectivity of cells is not defined.
1932 * \throw If any cell id in the array \a begin is not valid.
1934 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1935 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1937 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1939 if(getMeshDimension()!=-1)
1940 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1944 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1946 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1948 return const_cast<MEDCouplingUMesh *>(this);
1953 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1955 * 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.
1956 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1957 * The number of cells of \b this will remain the same with this method.
1959 * \param [in] begin begin of cell ids (included) of cells in this to assign
1960 * \param [in] end end of cell ids (excluded) of cells in this to assign
1961 * \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 ).
1962 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1964 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1966 checkConnectivityFullyDefined();
1967 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1968 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1969 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1970 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1972 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1973 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1974 throw INTERP_KERNEL::Exception(oss.str().c_str());
1976 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1977 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1979 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1980 throw INTERP_KERNEL::Exception(oss.str().c_str());
1982 int nbOfCells=getNumberOfCells();
1983 bool easyAssign=true;
1984 const int *connI=_nodal_connec_index->getConstPointer();
1985 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1986 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1988 if(*it>=0 && *it<nbOfCells)
1990 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1994 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1995 throw INTERP_KERNEL::Exception(oss.str().c_str());
2000 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2005 DataArrayInt *arrOut=0,*arrIOut=0;
2006 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2009 setConnectivity(arrOut,arrIOut,true);
2013 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2015 checkConnectivityFullyDefined();
2016 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2017 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2019 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2021 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2022 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2023 throw INTERP_KERNEL::Exception(oss.str().c_str());
2025 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2026 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2028 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2029 throw INTERP_KERNEL::Exception(oss.str().c_str());
2031 int nbOfCells=getNumberOfCells();
2032 bool easyAssign=true;
2033 const int *connI=_nodal_connec_index->getConstPointer();
2034 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2036 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2038 if(it>=0 && it<nbOfCells)
2040 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2044 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2045 throw INTERP_KERNEL::Exception(oss.str().c_str());
2050 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2055 DataArrayInt *arrOut=0,*arrIOut=0;
2056 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2059 setConnectivity(arrOut,arrIOut,true);
2064 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2065 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2066 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2067 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2069 * \param [in] begin input start of array of node ids.
2070 * \param [in] end input end of array of node ids.
2071 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2072 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2074 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2077 checkConnectivityFullyDefined();
2079 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2080 std::vector<bool> fastFinder(sz,false);
2081 for(const int *work=begin;work!=end;work++)
2082 if(*work>=0 && *work<sz)
2083 fastFinder[*work]=true;
2084 int nbOfCells=getNumberOfCells();
2085 const int *conn=getNodalConnectivity()->getConstPointer();
2086 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2087 for(int i=0;i<nbOfCells;i++)
2089 int ref=0,nbOfHit=0;
2090 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2094 if(fastFinder[*work2])
2097 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2098 cellIdsKept->pushBackSilent(i);
2100 cellIdsKeptArr=cellIdsKept.retn();
2104 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2105 * this->getMeshDimension(), that bound some cells of \a this mesh.
2106 * The cells of lower dimension to include to the result mesh are selected basing on
2107 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2108 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2109 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2110 * created mesh shares the node coordinates array with \a this mesh.
2111 * \param [in] begin - the array of node ids.
2112 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2113 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2114 * array \a begin are added, else cells whose any node is in the
2115 * array \a begin are added.
2116 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2117 * to delete this mesh using decrRef() as it is no more needed.
2118 * \throw If the coordinates array is not set.
2119 * \throw If the nodal connectivity of cells is not defined.
2120 * \throw If any node id in \a begin is not valid.
2122 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2123 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2125 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2128 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2129 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2130 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2131 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2135 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2136 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2137 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2138 * array of \a this mesh, else "free" nodes are removed from the result mesh
2139 * by calling zipCoords().
2140 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2141 * to delete this mesh using decrRef() as it is no more needed.
2142 * \throw If the coordinates array is not set.
2143 * \throw If the nodal connectivity of cells is not defined.
2145 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2146 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2148 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2150 DataArrayInt *desc=DataArrayInt::New();
2151 DataArrayInt *descIndx=DataArrayInt::New();
2152 DataArrayInt *revDesc=DataArrayInt::New();
2153 DataArrayInt *revDescIndx=DataArrayInt::New();
2155 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2158 descIndx->decrRef();
2159 int nbOfCells=meshDM1->getNumberOfCells();
2160 const int *revDescIndxC=revDescIndx->getConstPointer();
2161 std::vector<int> boundaryCells;
2162 for(int i=0;i<nbOfCells;i++)
2163 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2164 boundaryCells.push_back(i);
2165 revDescIndx->decrRef();
2166 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2171 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2172 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2173 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2175 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2177 checkFullyDefined();
2178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2183 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2184 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2188 const int *revDescPtr=revDesc->getConstPointer();
2189 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2190 int nbOfCells=getNumberOfCells();
2191 std::vector<bool> ret1(nbOfCells,false);
2193 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2194 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2195 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2197 DataArrayInt *ret2=DataArrayInt::New();
2199 int *ret2Ptr=ret2->getPointer();
2201 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2204 ret2->setName("BoundaryCells");
2209 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2210 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2211 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2212 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2214 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2215 * This method method returns cells ids set s = s1 + s2 where :
2217 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2218 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2220 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2221 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2223 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2224 * \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
2225 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2227 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2229 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2231 checkConnectivityFullyDefined();
2232 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2233 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2237 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2239 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2240 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2241 DataArrayInt *idsOtherInConsti=0;
2242 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2245 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2247 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2248 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2251 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2252 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2254 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2255 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2256 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2257 neighThisPartAuto=0;
2258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2259 const int li[2]={0,1};
2260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2261 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2265 cellIdsRk0=s0arr.retn();
2266 cellIdsRk1=s_renum1.retn();
2270 * 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
2271 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2273 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2275 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2282 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2283 revDesc=0; desc=0; descIndx=0;
2284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2286 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2290 * Finds nodes lying on the boundary of \a this mesh.
2291 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2292 * nodes. The caller is to delete this array using decrRef() as it is no
2294 * \throw If the coordinates array is not set.
2295 * \throw If the nodal connectivity of cells is node defined.
2297 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2298 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2300 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2302 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2303 return skin->computeFetchedNodeIds();
2306 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2309 return const_cast<MEDCouplingUMesh *>(this);
2313 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2314 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2315 * 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.
2316 * 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.
2317 * 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.
2319 * \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
2320 * parameter is altered during the call.
2321 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2322 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2323 * \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.
2325 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2327 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2328 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2330 checkFullyDefined();
2331 otherDimM1OnSameCoords.checkFullyDefined();
2332 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2334 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2335 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2336 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2337 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2340 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2341 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2345 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2350 DataArrayInt *idsTmp=0;
2351 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2355 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2356 DataArrayInt *tmp0=0,*tmp1=0;
2357 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2362 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2363 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2365 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2366 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2367 nodeIdsToDuplicate=s3.retn();
2371 * This method operates a modification of the connectivity and coords in \b this.
2372 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2373 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2374 * 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
2375 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2376 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2378 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2380 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2381 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2383 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2385 int nbOfNodes=getNumberOfNodes();
2386 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2387 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2391 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2392 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2393 * This method is a generalization of shiftNodeNumbersInConn().
2394 * \warning This method performs no check of validity of new ids. **Use it with care !**
2395 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2396 * this->getNumberOfNodes(), in "Old to New" mode.
2397 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2398 * \throw If the nodal connectivity of cells is not defined.
2400 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2401 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2403 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2405 checkConnectivityFullyDefined();
2406 int *conn=getNodalConnectivity()->getPointer();
2407 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2408 int nbOfCells=getNumberOfCells();
2409 for(int i=0;i<nbOfCells;i++)
2410 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2412 int& node=conn[iconn];
2413 if(node>=0)//avoid polyhedron separator
2415 node=newNodeNumbersO2N[node];
2418 _nodal_connec->declareAsNew();
2423 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2424 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2425 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2427 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2429 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2431 checkConnectivityFullyDefined();
2432 int *conn=getNodalConnectivity()->getPointer();
2433 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2434 int nbOfCells=getNumberOfCells();
2435 for(int i=0;i<nbOfCells;i++)
2436 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2438 int& node=conn[iconn];
2439 if(node>=0)//avoid polyhedron separator
2444 _nodal_connec->declareAsNew();
2449 * This method operates a modification of the connectivity in \b this.
2450 * 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.
2451 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2452 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2453 * 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
2454 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2455 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2457 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2458 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2460 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2461 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2462 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2464 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2466 checkConnectivityFullyDefined();
2467 std::map<int,int> m;
2469 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2471 int *conn=getNodalConnectivity()->getPointer();
2472 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2473 int nbOfCells=getNumberOfCells();
2474 for(int i=0;i<nbOfCells;i++)
2475 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2477 int& node=conn[iconn];
2478 if(node>=0)//avoid polyhedron separator
2480 std::map<int,int>::iterator it=m.find(node);
2489 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2491 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2492 * After the call of this method the number of cells remains the same as before.
2494 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2495 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2496 * be strictly in [0;this->getNumberOfCells()).
2498 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2499 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2500 * should be contained in[0;this->getNumberOfCells()).
2502 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2504 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2506 checkConnectivityFullyDefined();
2507 int nbCells=getNumberOfCells();
2508 const int *array=old2NewBg;
2510 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2512 const int *conn=_nodal_connec->getConstPointer();
2513 const int *connI=_nodal_connec_index->getConstPointer();
2514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2516 const int *n2oPtr=n2o->begin();
2517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2518 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2519 newConn->copyStringInfoFrom(*_nodal_connec);
2520 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2521 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2522 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2524 int *newC=newConn->getPointer();
2525 int *newCI=newConnI->getPointer();
2528 for(int i=0;i<nbCells;i++)
2531 int nbOfElts=connI[pos+1]-connI[pos];
2532 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2537 setConnectivity(newConn,newConnI);
2539 free(const_cast<int *>(array));
2543 * Finds cells whose bounding boxes intersect a given bounding box.
2544 * \param [in] bbox - an array defining the bounding box via coordinates of its
2545 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2547 * \param [in] eps - a factor used to increase size of the bounding box of cell
2548 * before comparing it with \a bbox. This factor is multiplied by the maximal
2549 * extent of the bounding box of cell to produce an addition to this bounding box.
2550 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2551 * cells. The caller is to delete this array using decrRef() as it is no more
2553 * \throw If the coordinates array is not set.
2554 * \throw If the nodal connectivity of cells is not defined.
2556 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2557 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2559 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2561 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2562 if(getMeshDimension()==-1)
2564 elems->pushBackSilent(0);
2565 return elems.retn();
2567 int dim=getSpaceDimension();
2568 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2569 const int* conn = getNodalConnectivity()->getConstPointer();
2570 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2571 const double* coords = getCoords()->getConstPointer();
2572 int nbOfCells=getNumberOfCells();
2573 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2575 for (int i=0; i<dim; i++)
2577 elem_bb[i*2]=std::numeric_limits<double>::max();
2578 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2581 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2583 int node= conn[inode];
2584 if(node>=0)//avoid polyhedron separator
2586 for (int idim=0; idim<dim; idim++)
2588 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2590 elem_bb[idim*2] = coords[node*dim+idim] ;
2592 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2594 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2599 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2600 elems->pushBackSilent(ielem);
2602 return elems.retn();
2606 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2607 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2608 * added in 'elems' parameter.
2610 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2613 if(getMeshDimension()==-1)
2615 elems->pushBackSilent(0);
2616 return elems.retn();
2618 int dim=getSpaceDimension();
2619 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2620 const int* conn = getNodalConnectivity()->getConstPointer();
2621 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2622 const double* coords = getCoords()->getConstPointer();
2623 int nbOfCells=getNumberOfCells();
2624 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2626 for (int i=0; i<dim; i++)
2628 elem_bb[i*2]=std::numeric_limits<double>::max();
2629 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2632 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2634 int node= conn[inode];
2635 if(node>=0)//avoid polyhedron separator
2637 for (int idim=0; idim<dim; idim++)
2639 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2641 elem_bb[idim*2] = coords[node*dim+idim] ;
2643 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2645 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2650 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2651 elems->pushBackSilent(ielem);
2653 return elems.retn();
2657 * Returns a type of a cell by its id.
2658 * \param [in] cellId - the id of the cell of interest.
2659 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2660 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2662 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2664 const int *ptI=_nodal_connec_index->getConstPointer();
2665 const int *pt=_nodal_connec->getConstPointer();
2666 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2667 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2670 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2671 throw INTERP_KERNEL::Exception(oss.str().c_str());
2676 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2677 * This method does not throw exception if geometric type \a type is not in \a this.
2678 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2679 * The coordinates array is not considered here.
2681 * \param [in] type the geometric type
2682 * \return cell ids in this having geometric type \a type.
2684 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2689 checkConnectivityFullyDefined();
2690 int nbCells=getNumberOfCells();
2691 int mdim=getMeshDimension();
2692 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2693 if(mdim!=(int)cm.getDimension())
2694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2695 const int *ptI=_nodal_connec_index->getConstPointer();
2696 const int *pt=_nodal_connec->getConstPointer();
2697 for(int i=0;i<nbCells;i++)
2699 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2700 ret->pushBackSilent(i);
2706 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2708 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2710 const int *ptI=_nodal_connec_index->getConstPointer();
2711 const int *pt=_nodal_connec->getConstPointer();
2712 int nbOfCells=getNumberOfCells();
2714 for(int i=0;i<nbOfCells;i++)
2715 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2721 * Returns the nodal connectivity of a given cell.
2722 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2723 * all returned node ids can be used in getCoordinatesOfNode().
2724 * \param [in] cellId - an id of the cell of interest.
2725 * \param [in,out] conn - a vector where the node ids are appended. It is not
2726 * cleared before the appending.
2727 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2729 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2731 const int *ptI=_nodal_connec_index->getConstPointer();
2732 const int *pt=_nodal_connec->getConstPointer();
2733 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2738 std::string MEDCouplingUMesh::simpleRepr() const
2740 static const char msg0[]="No coordinates specified !";
2741 std::ostringstream ret;
2742 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2743 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2745 double tt=getTime(tmpp1,tmpp2);
2746 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2747 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2749 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2751 { ret << " Mesh dimension has not been set or is invalid !"; }
2754 const int spaceDim=getSpaceDimension();
2755 ret << spaceDim << "\nInfo attached on space dimension : ";
2756 for(int i=0;i<spaceDim;i++)
2757 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2761 ret << msg0 << "\n";
2762 ret << "Number of nodes : ";
2764 ret << getNumberOfNodes() << "\n";
2766 ret << msg0 << "\n";
2767 ret << "Number of cells : ";
2768 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2769 ret << getNumberOfCells() << "\n";
2771 ret << "No connectivity specified !" << "\n";
2772 ret << "Cell types present : ";
2773 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2775 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2776 ret << cm.getRepr() << " ";
2782 std::string MEDCouplingUMesh::advancedRepr() const
2784 std::ostringstream ret;
2785 ret << simpleRepr();
2786 ret << "\nCoordinates array : \n___________________\n\n";
2788 _coords->reprWithoutNameStream(ret);
2790 ret << "No array set !\n";
2791 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2792 reprConnectivityOfThisLL(ret);
2797 * This method returns a C++ code that is a dump of \a this.
2798 * This method will throw if this is not fully defined.
2800 std::string MEDCouplingUMesh::cppRepr() const
2802 static const char coordsName[]="coords";
2803 static const char connName[]="conn";
2804 static const char connIName[]="connI";
2805 checkFullyDefined();
2806 std::ostringstream ret; ret << "// coordinates" << std::endl;
2807 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2808 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2809 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2810 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2811 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2812 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2813 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2817 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2819 std::ostringstream ret;
2820 reprConnectivityOfThisLL(ret);
2825 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2826 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2827 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2830 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2831 * 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
2832 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2834 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2836 int mdim=getMeshDimension();
2838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2839 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2841 bool needToCpyCT=true;
2844 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2852 if(!_nodal_connec_index)
2854 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2859 tmp2=_nodal_connec_index;
2862 ret->setConnectivity(tmp1,tmp2,false);
2867 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2868 ret->setCoords(coords);
2871 ret->setCoords(_coords);
2875 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2877 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2879 int nbOfCells=getNumberOfCells();
2880 const int *c=_nodal_connec->getConstPointer();
2881 const int *ci=_nodal_connec_index->getConstPointer();
2882 for(int i=0;i<nbOfCells;i++)
2884 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2885 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2886 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2891 stream << "Connectivity not defined !\n";
2894 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2896 const int *ptI=_nodal_connec_index->getConstPointer();
2897 const int *pt=_nodal_connec->getConstPointer();
2898 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2899 return ptI[cellId+1]-ptI[cellId]-1;
2901 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2905 * Returns types of cells of the specified part of \a this mesh.
2906 * This method avoids computing sub-mesh explicitely to get its types.
2907 * \param [in] begin - an array of cell ids of interest.
2908 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2909 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2910 * describing the cell types.
2911 * \throw If the coordinates array is not set.
2912 * \throw If the nodal connectivity of cells is not defined.
2915 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2917 checkFullyDefined();
2918 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2919 const int *conn=_nodal_connec->getConstPointer();
2920 const int *connIndex=_nodal_connec_index->getConstPointer();
2921 for(const int *w=begin;w!=end;w++)
2922 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2927 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2928 * a set of types of cells constituting \a this mesh.
2929 * This method is for advanced users having prepared their connectivity before. For
2930 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2931 * \param [in] conn - the nodal connectivity array.
2932 * \param [in] connIndex - the nodal connectivity index array.
2933 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2936 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2938 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2939 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2940 if(isComputingTypes)
2946 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2947 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2949 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2950 _nodal_connec(0),_nodal_connec_index(0),
2951 _types(other._types)
2953 if(other._nodal_connec)
2954 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2955 if(other._nodal_connec_index)
2956 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2959 MEDCouplingUMesh::~MEDCouplingUMesh()
2962 _nodal_connec->decrRef();
2963 if(_nodal_connec_index)
2964 _nodal_connec_index->decrRef();
2968 * Recomputes a set of cell types of \a this mesh. For more info see
2969 * \ref MEDCouplingUMeshNodalConnectivity.
2971 void MEDCouplingUMesh::computeTypes()
2973 if(_nodal_connec && _nodal_connec_index)
2976 const int *conn=_nodal_connec->getConstPointer();
2977 const int *connIndex=_nodal_connec_index->getConstPointer();
2978 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2980 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2981 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2986 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2988 void MEDCouplingUMesh::checkFullyDefined() const
2990 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2991 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2995 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2997 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
2999 if(!_nodal_connec_index || !_nodal_connec)
3000 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3004 * Returns a number of cells constituting \a this mesh.
3005 * \return int - the number of cells in \a this mesh.
3006 * \throw If the nodal connectivity of cells is not defined.
3008 int MEDCouplingUMesh::getNumberOfCells() const
3010 if(_nodal_connec_index)
3011 return _nodal_connec_index->getNumberOfTuples()-1;
3016 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3020 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3021 * mesh. For more info see \ref MEDCouplingMeshesPage.
3022 * \return int - the dimension of \a this mesh.
3023 * \throw If the mesh dimension is not defined using setMeshDimension().
3025 int MEDCouplingUMesh::getMeshDimension() const
3028 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3033 * Returns a length of the nodal connectivity array.
3034 * This method is for test reason. Normally the integer returned is not useable by
3035 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3036 * \return int - the length of the nodal connectivity array.
3038 int MEDCouplingUMesh::getMeshLength() const
3040 return _nodal_connec->getNbOfElems();
3044 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3046 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3048 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3049 tinyInfo.push_back(getMeshDimension());
3050 tinyInfo.push_back(getNumberOfCells());
3052 tinyInfo.push_back(getMeshLength());
3054 tinyInfo.push_back(-1);
3058 * First step of unserialization process.
3060 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3062 return tinyInfo[6]<=0;
3066 * Second step of serialization process.
3067 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3069 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3071 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3073 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3077 * Third and final step of serialization process.
3079 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3081 MEDCouplingPointSet::serialize(a1,a2);
3082 if(getMeshDimension()>-1)
3084 a1=DataArrayInt::New();
3085 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3086 int *ptA1=a1->getPointer();
3087 const int *conn=getNodalConnectivity()->getConstPointer();
3088 const int *index=getNodalConnectivityIndex()->getConstPointer();
3089 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3090 std::copy(conn,conn+getMeshLength(),ptA1);
3097 * Second and final unserialization process.
3098 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3100 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3102 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3103 setMeshDimension(tinyInfo[5]);
3107 const int *recvBuffer=a1->getConstPointer();
3108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3109 myConnecIndex->alloc(tinyInfo[6]+1,1);
3110 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3112 myConnec->alloc(tinyInfo[7],1);
3113 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3114 setConnectivity(myConnec, myConnecIndex);
3119 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3120 * CellIds are given using range specified by a start an end and step.
3122 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3124 checkFullyDefined();
3125 int ncell=getNumberOfCells();
3126 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3127 ret->_mesh_dim=_mesh_dim;
3128 ret->setCoords(_coords);
3129 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3131 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3133 const int *conn=_nodal_connec->getConstPointer();
3134 const int *connIndex=_nodal_connec_index->getConstPointer();
3135 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3137 if(work>=0 && work<ncell)
3139 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3143 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3144 throw INTERP_KERNEL::Exception(oss.str().c_str());
3147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3148 int *newConnPtr=newConn->getPointer();
3149 std::set<INTERP_KERNEL::NormalizedCellType> types;
3151 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3153 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3154 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3156 ret->setConnectivity(newConn,newConnI,false);
3158 ret->copyTinyInfoFrom(this);
3163 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3164 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3165 * The return newly allocated mesh will share the same coordinates as \a this.
3167 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3169 checkConnectivityFullyDefined();
3170 int ncell=getNumberOfCells();
3171 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3172 ret->_mesh_dim=_mesh_dim;
3173 ret->setCoords(_coords);
3174 std::size_t nbOfElemsRet=std::distance(begin,end);
3175 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3177 const int *conn=_nodal_connec->getConstPointer();
3178 const int *connIndex=_nodal_connec_index->getConstPointer();
3180 for(const int *work=begin;work!=end;work++,newNbring++)
3182 if(*work>=0 && *work<ncell)
3183 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3187 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3188 throw INTERP_KERNEL::Exception(oss.str().c_str());
3191 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3192 int *connRetWork=connRet;
3193 std::set<INTERP_KERNEL::NormalizedCellType> types;
3194 for(const int *work=begin;work!=end;work++)
3196 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3197 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3200 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3202 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3203 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3205 ret->copyTinyInfoFrom(this);
3210 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3212 * For 1D cells, the returned field contains lengths.<br>
3213 * For 2D cells, the returned field contains areas.<br>
3214 * For 3D cells, the returned field contains volumes.
3215 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3216 * orientation, i.e. the volume is always positive.
3217 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3218 * and one time . The caller is to delete this field using decrRef() as it is no
3221 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3223 std::string name="MeasureOfMesh_";
3225 int nbelem=getNumberOfCells();
3226 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3227 field->setName(name.c_str());
3228 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3229 array->alloc(nbelem,1);
3230 double *area_vol=array->getPointer();
3231 field->setArray(array) ; array=0;
3232 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3233 field->synchronizeTimeWithMesh();
3234 if(getMeshDimension()!=-1)
3237 INTERP_KERNEL::NormalizedCellType type;
3238 int dim_space=getSpaceDimension();
3239 const double *coords=getCoords()->getConstPointer();
3240 const int *connec=getNodalConnectivity()->getConstPointer();
3241 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3242 for(int iel=0;iel<nbelem;iel++)
3244 ipt=connec_index[iel];
3245 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3246 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);
3249 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3253 area_vol[0]=std::numeric_limits<double>::max();
3255 return field.retn();
3259 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3261 * For 1D cells, the returned array contains lengths.<br>
3262 * For 2D cells, the returned array contains areas.<br>
3263 * For 3D cells, the returned array contains volumes.
3264 * This method avoids building explicitly a part of \a this mesh to perform the work.
3265 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3266 * orientation, i.e. the volume is always positive.
3267 * \param [in] begin - an array of cell ids of interest.
3268 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3269 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3270 * delete this array using decrRef() as it is no more needed.
3272 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3273 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3274 * \sa getMeasureField()
3276 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3278 std::string name="PartMeasureOfMesh_";
3280 int nbelem=(int)std::distance(begin,end);
3281 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3282 array->setName(name.c_str());
3283 array->alloc(nbelem,1);
3284 double *area_vol=array->getPointer();
3285 if(getMeshDimension()!=-1)
3288 INTERP_KERNEL::NormalizedCellType type;
3289 int dim_space=getSpaceDimension();
3290 const double *coords=getCoords()->getConstPointer();
3291 const int *connec=getNodalConnectivity()->getConstPointer();
3292 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3293 for(const int *iel=begin;iel!=end;iel++)
3295 ipt=connec_index[*iel];
3296 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3297 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3300 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3304 area_vol[0]=std::numeric_limits<double>::max();
3306 return array.retn();
3310 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3311 * \a this one. The returned field contains the dual cell volume for each corresponding
3312 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3313 * the dual mesh in P1 sens of \a this.<br>
3314 * For 1D cells, the returned field contains lengths.<br>
3315 * For 2D cells, the returned field contains areas.<br>
3316 * For 3D cells, the returned field contains volumes.
3317 * This method is useful to check "P1*" conservative interpolators.
3318 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3319 * orientation, i.e. the volume is always positive.
3320 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3321 * nodes and one time. The caller is to delete this array using decrRef() as
3322 * it is no more needed.
3324 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3326 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3327 std::string name="MeasureOnNodeOfMesh_";
3329 int nbNodes=getNumberOfNodes();
3330 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3331 double cst=1./((double)getMeshDimension()+1.);
3332 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3333 array->alloc(nbNodes,1);
3334 double *valsToFill=array->getPointer();
3335 std::fill(valsToFill,valsToFill+nbNodes,0.);
3336 const double *values=tmp->getArray()->getConstPointer();
3337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3339 getReverseNodalConnectivity(da,daInd);
3340 const int *daPtr=da->getConstPointer();
3341 const int *daIPtr=daInd->getConstPointer();
3342 for(int i=0;i<nbNodes;i++)
3343 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3344 valsToFill[i]+=cst*values[*cell];
3346 ret->setArray(array);
3351 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3352 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3353 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3354 * and are normalized.
3355 * <br> \a this can be either
3356 * - a 2D mesh in 2D or 3D space or
3357 * - an 1D mesh in 2D space.
3359 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3360 * cells and one time. The caller is to delete this field using decrRef() as
3361 * it is no more needed.
3362 * \throw If the nodal connectivity of cells is not defined.
3363 * \throw If the coordinates array is not set.
3364 * \throw If the mesh dimension is not set.
3365 * \throw If the mesh and space dimension is not as specified above.
3367 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3369 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3370 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3371 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3372 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3373 int nbOfCells=getNumberOfCells();
3374 int nbComp=getMeshDimension()+1;
3375 array->alloc(nbOfCells,nbComp);
3376 double *vals=array->getPointer();
3377 const int *connI=_nodal_connec_index->getConstPointer();
3378 const int *conn=_nodal_connec->getConstPointer();
3379 const double *coords=_coords->getConstPointer();
3380 if(getMeshDimension()==2)
3382 if(getSpaceDimension()==3)
3384 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3385 const double *locPtr=loc->getConstPointer();
3386 for(int i=0;i<nbOfCells;i++,vals+=3)
3388 int offset=connI[i];
3389 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3390 double n=INTERP_KERNEL::norm<3>(vals);
3391 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3397 const double *isAbsPtr=isAbs->getArray()->begin();
3398 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3399 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3402 else//meshdimension==1
3405 for(int i=0;i<nbOfCells;i++)
3407 int offset=connI[i];
3408 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3409 double n=INTERP_KERNEL::norm<2>(tmp);
3410 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3415 ret->setArray(array);
3417 ret->synchronizeTimeWithSupport();
3422 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3423 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3424 * and are normalized.
3425 * <br> \a this can be either
3426 * - a 2D mesh in 2D or 3D space or
3427 * - an 1D mesh in 2D space.
3429 * This method avoids building explicitly a part of \a this mesh to perform the work.
3430 * \param [in] begin - an array of cell ids of interest.
3431 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3432 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3433 * cells and one time. The caller is to delete this field using decrRef() as
3434 * it is no more needed.
3435 * \throw If the nodal connectivity of cells is not defined.
3436 * \throw If the coordinates array is not set.
3437 * \throw If the mesh dimension is not set.
3438 * \throw If the mesh and space dimension is not as specified above.
3439 * \sa buildOrthogonalField()
3441 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3442 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3444 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3446 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3447 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3448 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3449 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3450 std::size_t nbelems=std::distance(begin,end);
3451 int nbComp=getMeshDimension()+1;
3452 array->alloc((int)nbelems,nbComp);
3453 double *vals=array->getPointer();
3454 const int *connI=_nodal_connec_index->getConstPointer();
3455 const int *conn=_nodal_connec->getConstPointer();
3456 const double *coords=_coords->getConstPointer();
3457 if(getMeshDimension()==2)
3459 if(getSpaceDimension()==3)
3461 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3462 const double *locPtr=loc->getConstPointer();
3463 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3465 int offset=connI[*i];
3466 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3467 double n=INTERP_KERNEL::norm<3>(vals);
3468 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3473 for(std::size_t i=0;i<nbelems;i++)
3474 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3477 else//meshdimension==1
3480 for(const int *i=begin;i!=end;i++)
3482 int offset=connI[*i];
3483 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3484 double n=INTERP_KERNEL::norm<2>(tmp);
3485 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3490 ret->setArray(array);
3492 ret->synchronizeTimeWithSupport();
3497 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3498 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3499 * and are \b not normalized.
3500 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3501 * cells and one time. The caller is to delete this field using decrRef() as
3502 * it is no more needed.
3503 * \throw If the nodal connectivity of cells is not defined.
3504 * \throw If the coordinates array is not set.
3505 * \throw If \a this->getMeshDimension() != 1.
3506 * \throw If \a this mesh includes cells of type other than SEG2.
3508 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3510 if(getMeshDimension()!=1)
3511 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3512 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3513 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3514 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3515 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3516 int nbOfCells=getNumberOfCells();
3517 int spaceDim=getSpaceDimension();
3518 array->alloc(nbOfCells,spaceDim);
3519 double *pt=array->getPointer();
3520 const double *coo=getCoords()->getConstPointer();
3521 std::vector<int> conn;
3523 for(int i=0;i<nbOfCells;i++)
3526 getNodeIdsOfCell(i,conn);
3527 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3529 ret->setArray(array);
3531 ret->synchronizeTimeWithSupport();
3536 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3537 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3538 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3539 * from. If a result face is shared by two 3D cells, then the face in included twice in
3541 * \param [in] origin - 3 components of a point defining location of the plane.
3542 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3543 * must be greater than 1e-6.
3544 * \param [in] eps - half-thickness of the plane.
3545 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3546 * producing correspondent 2D cells. The caller is to delete this array
3547 * using decrRef() as it is no more needed.
3548 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3549 * not share the node coordinates array with \a this mesh. The caller is to
3550 * delete this mesh using decrRef() as it is no more needed.
3551 * \throw If the coordinates array is not set.
3552 * \throw If the nodal connectivity of cells is not defined.
3553 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3554 * \throw If magnitude of \a vec is less than 1e-6.
3555 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3556 * \throw If \a this includes quadratic cells.
3558 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3560 checkFullyDefined();
3561 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3562 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3563 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3564 if(candidates->empty())
3565 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3566 std::vector<int> nodes;
3567 DataArrayInt *cellIds1D=0;
3568 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3569 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3571 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3572 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3573 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3574 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3575 revDesc2=0; revDescIndx2=0;
3576 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3577 revDesc1=0; revDescIndx1=0;
3578 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3581 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3582 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3584 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3585 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3586 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3587 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3588 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3589 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3590 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3591 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3592 if(cellIds2->empty())
3593 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3594 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3595 ret->setCoords(mDesc1->getCoords());
3596 ret->setConnectivity(conn,connI,true);
3597 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3602 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3603 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
3604 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3606 * \param [in] origin - 3 components of a point defining location of the plane.
3607 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3608 * must be greater than 1e-6.
3609 * \param [in] eps - half-thickness of the plane.
3610 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3611 * producing correspondent segments. The caller is to delete this array
3612 * using decrRef() as it is no more needed.
3613 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3614 * mesh in 3D space. This mesh does not share the node coordinates array with
3615 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3617 * \throw If the coordinates array is not set.
3618 * \throw If the nodal connectivity of cells is not defined.
3619 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3620 * \throw If magnitude of \a vec is less than 1e-6.
3621 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3622 * \throw If \a this includes quadratic cells.
3624 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3626 checkFullyDefined();
3627 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3630 if(candidates->empty())
3631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3632 std::vector<int> nodes;
3633 DataArrayInt *cellIds1D=0;
3634 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3635 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3640 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3641 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3642 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3644 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3645 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3647 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3648 int ncellsSub=subMesh->getNumberOfCells();
3649 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3650 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3651 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3652 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3655 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3656 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3657 for(int i=0;i<ncellsSub;i++)
3659 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3661 if(cut3DSurf[i].first!=-2)
3663 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3664 connI->pushBackSilent(conn->getNumberOfTuples());
3665 cellIds2->pushBackSilent(i);
3669 int cellId3DSurf=cut3DSurf[i].second;
3670 int offset=nodalI[cellId3DSurf]+1;
3671 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3672 for(int j=0;j<nbOfEdges;j++)
3674 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3675 connI->pushBackSilent(conn->getNumberOfTuples());
3676 cellIds2->pushBackSilent(cellId3DSurf);
3681 if(cellIds2->empty())
3682 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3683 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3684 ret->setCoords(mDesc1->getCoords());
3685 ret->setConnectivity(conn,connI,true);
3686 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3691 * Finds cells whose bounding boxes intersect a given plane.
3692 * \param [in] origin - 3 components of a point defining location of the plane.
3693 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3694 * must be greater than 1e-6.
3695 * \param [in] eps - half-thickness of the plane.
3696 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3697 * cells. The caller is to delete this array using decrRef() as it is no more
3699 * \throw If the coordinates array is not set.
3700 * \throw If the nodal connectivity of cells is not defined.
3701 * \throw If \a this->getSpaceDimension() != 3.
3702 * \throw If magnitude of \a vec is less than 1e-6.
3703 * \sa buildSlice3D()
3705 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3707 checkFullyDefined();
3708 if(getSpaceDimension()!=3)
3709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3710 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3712 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3714 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3715 double angle=acos(vec[2]/normm);
3716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3720 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3721 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3722 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3724 mw->getBoundingBox(bbox);
3725 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3726 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3730 getBoundingBox(bbox);
3731 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3732 cellIds=getCellsInBoundingBox(bbox,eps);
3734 return cellIds.retn();
3738 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3739 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3740 * No consideration of coordinate is done by this method.
3741 * 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)
3742 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3744 bool MEDCouplingUMesh::isContiguous1D() const
3746 if(getMeshDimension()!=1)
3747 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3748 int nbCells=getNumberOfCells();
3750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3751 const int *connI=_nodal_connec_index->getConstPointer();
3752 const int *conn=_nodal_connec->getConstPointer();
3753 int ref=conn[connI[0]+2];
3754 for(int i=1;i<nbCells;i++)
3756 if(conn[connI[i]+1]!=ref)
3758 ref=conn[connI[i]+2];
3764 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3765 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3766 * \param pt reference point of the line
3767 * \param v normalized director vector of the line
3768 * \param eps max precision before throwing an exception
3769 * \param res output of size this->getNumberOfCells
3771 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3773 if(getMeshDimension()!=1)
3774 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3775 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3776 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3777 if(getSpaceDimension()!=3)
3778 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3779 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3780 const double *fPtr=f->getArray()->getConstPointer();
3782 for(int i=0;i<getNumberOfCells();i++)
3784 const double *tmp1=fPtr+3*i;
3785 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3786 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3787 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3788 double n1=INTERP_KERNEL::norm<3>(tmp);
3789 n1/=INTERP_KERNEL::norm<3>(tmp1);
3791 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3793 const double *coo=getCoords()->getConstPointer();
3794 for(int i=0;i<getNumberOfNodes();i++)
3796 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3797 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3798 res[i]=std::accumulate(tmp,tmp+3,0.);
3803 * 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.
3804 * \a this is expected to be a mesh so that its space dimension is equal to its
3805 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3806 * 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).
3808 * 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
3809 * 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).
3810 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3812 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3813 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3815 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3816 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3817 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3818 * \return the positive value of the distance.
3819 * \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
3821 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3823 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3825 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3826 if(meshDim!=spaceDim-1)
3827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3828 if(meshDim!=2 && meshDim!=1)
3829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3830 checkFullyDefined();
3831 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3832 { 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()); }
3833 DataArrayInt *ret1=0;
3834 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3835 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3837 cellId=*ret1Safe->begin();
3838 return *ret0->begin();
3842 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3843 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3844 * 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
3845 * 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).
3846 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3848 * \a this is expected to be a mesh so that its space dimension is equal to its
3849 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3850 * 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).
3852 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3853 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3855 * \param [in] pts the list of points in which each tuple represents a point
3856 * \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.
3857 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3858 * \throw if number of components of \a pts is not equal to the space dimension.
3859 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3860 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3862 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3865 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3866 pts->checkAllocated();
3867 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3868 if(meshDim!=spaceDim-1)
3869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3870 if(meshDim!=2 && meshDim!=1)
3871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3872 if(pts->getNumberOfComponents()!=spaceDim)
3874 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3875 throw INTERP_KERNEL::Exception(oss.str().c_str());
3877 checkFullyDefined();
3878 int nbCells=getNumberOfCells();
3880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3881 int nbOfPts=pts->getNumberOfTuples();
3882 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3884 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3885 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3886 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3887 const double *bbox(bboxArr->begin());
3892 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3893 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3895 double x=std::numeric_limits<double>::max();
3896 std::vector<int> elems;
3897 myTree.getMinDistanceOfMax(ptsPtr,x);
3898 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3899 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3905 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3906 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3908 double x=std::numeric_limits<double>::max();
3909 std::vector<int> elems;
3910 myTree.getMinDistanceOfMax(ptsPtr,x);
3911 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3912 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3919 cellIds=ret1.retn();
3924 * \param [in] pt the start pointer (included) of the coordinates of the point
3925 * \param [in] cellIdsBg the start pointer (included) of cellIds
3926 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3927 * \param [in] nc nodal connectivity
3928 * \param [in] ncI nodal connectivity index
3929 * \param [in,out] ret0 the min distance between \a this and the external input point
3930 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3931 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3933 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)
3936 ret0=std::numeric_limits<double>::max();
3937 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3939 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3941 case INTERP_KERNEL::NORM_TRI3:
3943 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3945 { ret0=tmp; cellId=*zeCell; }
3948 case INTERP_KERNEL::NORM_QUAD4:
3949 case INTERP_KERNEL::NORM_POLYGON:
3951 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3953 { ret0=tmp; cellId=*zeCell; }
3957 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3963 * \param [in] pt the start pointer (included) of the coordinates of the point
3964 * \param [in] cellIdsBg the start pointer (included) of cellIds
3965 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3966 * \param [in] nc nodal connectivity
3967 * \param [in] ncI nodal connectivity index
3968 * \param [in,out] ret0 the min distance between \a this and the external input point
3969 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3970 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3972 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)
3975 ret0=std::numeric_limits<double>::max();
3976 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3978 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3980 case INTERP_KERNEL::NORM_SEG2:
3982 std::size_t uselessEntry=0;
3983 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3986 { ret0=tmp; cellId=*zeCell; }
3990 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3996 * Finds cells in contact with a ball (i.e. a point with precision).
3997 * \warning This method is suitable if the caller intends to evaluate only one
3998 * point, for more points getCellsContainingPoints() is recommended as it is
4000 * \param [in] pos - array of coordinates of the ball central point.
4001 * \param [in] eps - ball radius.
4002 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4003 * if there are no such cells.
4004 * \throw If the coordinates array is not set.
4005 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4007 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4009 std::vector<int> elts;
4010 getCellsContainingPoint(pos,eps,elts);
4013 return elts.front();
4017 * Finds cells in contact with a ball (i.e. a point with precision).
4018 * \warning This method is suitable if the caller intends to evaluate only one
4019 * point, for more points getCellsContainingPoints() is recommended as it is
4021 * \param [in] pos - array of coordinates of the ball central point.
4022 * \param [in] eps - ball radius.
4023 * \param [out] elts - vector returning ids of the found cells. It is cleared
4024 * before inserting ids.
4025 * \throw If the coordinates array is not set.
4026 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4028 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4029 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4031 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4033 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4034 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4035 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4040 namespace ParaMEDMEM
4042 template<const int SPACEDIMM>
4046 static const int MY_SPACEDIM=SPACEDIMM;
4047 static const int MY_MESHDIM=8;
4048 typedef int MyConnType;
4049 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4051 // useless, but for windows compilation ...
4052 const double* getCoordinatesPtr() const { return 0; }
4053 const int* getConnectivityPtr() const { return 0; }
4054 const int* getConnectivityIndexPtr() const { return 0; }
4055 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4059 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4061 INTERP_KERNEL::Edge *ret=0;
4064 case INTERP_KERNEL::NORM_SEG2:
4066 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4069 case INTERP_KERNEL::NORM_SEG3:
4071 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4072 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4073 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4074 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4075 bool colinearity=inters.areColinears();
4076 delete e1; delete e2;
4078 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4080 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4081 mapp2[bg[2]].second=false;
4085 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4091 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4092 * the global mesh 'mDesc'.
4093 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4094 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4096 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4097 std::map<INTERP_KERNEL::Node *,int>& mapp)
4098 throw(INTERP_KERNEL::Exception)
4101 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.
4102 const double *coo=mDesc->getCoords()->getConstPointer();
4103 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4104 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4106 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4107 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4108 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4110 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4111 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4113 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4114 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4116 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4117 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4119 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4121 if((*it2).second.second)
4122 mapp[(*it2).second.first]=(*it2).first;
4123 ((*it2).second.first)->decrRef();
4128 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4132 int locId=nodeId-offset2;
4133 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4137 int locId=nodeId-offset1;
4138 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4140 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4144 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4146 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4147 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4148 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4150 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4152 int eltId1=abs(*desc1)-1;
4153 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4155 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4156 if(it==mappRev.end())
4158 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4169 template<int SPACEDIM>
4170 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4171 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4173 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4174 int *eltsIndexPtr(eltsIndex->getPointer());
4175 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4176 const double *bbox(bboxArr->begin());
4177 int nbOfCells=getNumberOfCells();
4178 const int *conn=_nodal_connec->getConstPointer();
4179 const int *connI=_nodal_connec_index->getConstPointer();
4180 double bb[2*SPACEDIM];
4181 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4182 for(int i=0;i<nbOfPoints;i++)
4184 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4185 for(int j=0;j<SPACEDIM;j++)
4187 bb[2*j]=pos[SPACEDIM*i+j];
4188 bb[2*j+1]=pos[SPACEDIM*i+j];
4190 std::vector<int> candidates;
4191 myTree.getIntersectingElems(bb,candidates);
4192 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4194 int sz=connI[(*iter)+1]-connI[*iter]-1;
4195 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4196 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4197 coords,conn+connI[*iter]+1,sz,eps))
4199 eltsIndexPtr[i+1]++;
4200 elts->pushBackSilent(*iter);
4206 * Finds cells in contact with several balls (i.e. points with precision).
4207 * This method is an extension of getCellContainingPoint() and
4208 * getCellsContainingPoint() for the case of multiple points.
4209 * \param [in] pos - an array of coordinates of points in full interlace mode :
4210 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4211 * this->getSpaceDimension() * \a nbOfPoints
4212 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4213 * \param [in] eps - radius of balls (i.e. the precision).
4214 * \param [out] elts - vector returning ids of found cells.
4215 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4216 * dividing cell ids in \a elts into groups each referring to one
4217 * point. Its every element (except the last one) is an index pointing to the
4218 * first id of a group of cells. For example cells in contact with the *i*-th
4219 * point are described by following range of indices:
4220 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4221 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4222 * Number of cells in contact with the *i*-th point is
4223 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4224 * \throw If the coordinates array is not set.
4225 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4227 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4228 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4230 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4231 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4233 int spaceDim=getSpaceDimension();
4234 int mDim=getMeshDimension();
4239 const double *coords=_coords->getConstPointer();
4240 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4247 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4249 else if(spaceDim==2)
4253 const double *coords=_coords->getConstPointer();
4254 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4257 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4259 else if(spaceDim==1)
4263 const double *coords=_coords->getConstPointer();
4264 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4267 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4270 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4274 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4275 * least two its edges intersect each other anywhere except their extremities. An
4276 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4277 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4278 * cleared before filling in.
4279 * \param [in] eps - precision.
4280 * \throw If \a this->getMeshDimension() != 2.
4281 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4283 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4285 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4286 if(getMeshDimension()!=2)
4287 throw INTERP_KERNEL::Exception(msg);
4288 int spaceDim=getSpaceDimension();
4289 if(spaceDim!=2 && spaceDim!=3)
4290 throw INTERP_KERNEL::Exception(msg);
4291 const int *conn=_nodal_connec->getConstPointer();
4292 const int *connI=_nodal_connec_index->getConstPointer();
4293 int nbOfCells=getNumberOfCells();
4294 std::vector<double> cell2DinS2;
4295 for(int i=0;i<nbOfCells;i++)
4297 int offset=connI[i];
4298 int nbOfNodesForCell=connI[i+1]-offset-1;
4299 if(nbOfNodesForCell<=3)
4301 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4302 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4303 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4310 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4312 * 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.
4313 * 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.
4315 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4316 * This convex envelop is computed using Jarvis march algorithm.
4317 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4318 * 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)
4319 * 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.
4321 * \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.
4323 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4325 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4326 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4327 checkFullyDefined();
4328 const double *coords=getCoords()->getConstPointer();
4329 int nbOfCells=getNumberOfCells();
4330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4331 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4333 int *workIndexOut=nodalConnecIndexOut->getPointer();
4335 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4336 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4337 std::set<INTERP_KERNEL::NormalizedCellType> types;
4338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4339 isChanged->alloc(0,1);
4340 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4342 int pos=nodalConnecOut->getNumberOfTuples();
4343 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4344 isChanged->pushBackSilent(i);
4345 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4346 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4348 if(isChanged->empty())
4350 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4352 return isChanged.retn();
4356 * This method is \b NOT const because it can modify \a this.
4357 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4358 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4359 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4360 * \b 1 for translation and rotation around point of 'mesh1D'.
4361 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4363 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4365 checkFullyDefined();
4366 mesh1D->checkFullyDefined();
4367 if(!mesh1D->isContiguous1D())
4368 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4369 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4370 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4371 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4372 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4373 if(mesh1D->getMeshDimension()!=1)
4374 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4376 if(isPresenceOfQuadratic())
4378 if(mesh1D->isFullyQuadratic())
4381 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4384 int oldNbOfNodes=getNumberOfNodes();
4385 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4390 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4395 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4399 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4401 setCoords(newCoords);
4402 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4408 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4409 * If it is not the case an exception will be thrown.
4410 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4411 * intersection of plane defined by ('origin','vec').
4412 * This method has one in/out parameter : 'cut3DCurve'.
4413 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4414 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4415 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4416 * This method will throw an exception if \a this contains a non linear segment.
4418 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4420 checkFullyDefined();
4421 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4422 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4423 int ncells=getNumberOfCells();
4424 int nnodes=getNumberOfNodes();
4425 double vec2[3],vec3[3],vec4[3];
4426 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4429 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4430 const int *conn=_nodal_connec->getConstPointer();
4431 const int *connI=_nodal_connec_index->getConstPointer();
4432 const double *coo=_coords->getConstPointer();
4433 std::vector<double> addCoo;
4434 for(int i=0;i<ncells;i++)
4436 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4438 if(cut3DCurve[i]==-2)
4440 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4441 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];
4442 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4443 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4444 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4446 const double *st2=coo+3*st;
4447 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4448 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]));
4449 if(pos>eps && pos<1-eps)
4451 int nNode=((int)addCoo.size())/3;
4452 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4453 addCoo.insert(addCoo.end(),vec4,vec4+3);
4454 cut3DCurve[i]=nnodes+nNode;
4460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4464 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4465 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4466 coo2->alloc(newNbOfNodes,3);
4467 double *tmp=coo2->getPointer();
4468 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4469 std::copy(addCoo.begin(),addCoo.end(),tmp);
4470 DataArrayDouble::SetArrayIn(coo2,_coords);
4475 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4476 * \param mesh1D is the input 1D mesh used for translation computation.
4477 * \return newCoords new coords filled by this method.
4479 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4481 int oldNbOfNodes=getNumberOfNodes();
4482 int nbOf1DCells=mesh1D->getNumberOfCells();
4483 int spaceDim=getSpaceDimension();
4484 DataArrayDouble *ret=DataArrayDouble::New();
4485 std::vector<bool> isQuads;
4486 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4487 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4488 double *retPtr=ret->getPointer();
4489 const double *coords=getCoords()->getConstPointer();
4490 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4492 std::vector<double> c;
4496 for(int i=0;i<nbOf1DCells;i++)
4499 mesh1D->getNodeIdsOfCell(i,v);
4501 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4502 mesh1D->getCoordinatesOfNode(v[0],c);
4503 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4504 for(int j=0;j<oldNbOfNodes;j++)
4505 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4509 mesh1D->getCoordinatesOfNode(v[1],c);
4510 mesh1D->getCoordinatesOfNode(v[0],c);
4511 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4512 for(int j=0;j<oldNbOfNodes;j++)
4513 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4516 ret->copyStringInfoFrom(*getCoords());
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::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4527 if(mesh1D->getSpaceDimension()==2)
4528 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4529 if(mesh1D->getSpaceDimension()==3)
4530 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4531 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4535 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4536 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4537 * \return newCoords new coords filled by this method.
4539 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4542 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4543 int oldNbOfNodes=getNumberOfNodes();
4544 int nbOf1DCells=mesh1D->getNumberOfCells();
4546 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4547 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4548 int nbOfLevsInVec=nbOf1DCells+1;
4549 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4550 double *retPtr=ret->getPointer();
4551 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4552 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4553 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4554 tmp->setCoords(tmp2);
4555 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4556 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4557 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4558 for(int i=1;i<nbOfLevsInVec;i++)
4560 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4561 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4562 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4563 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4564 tmp->translate(vec);
4565 double tmp3[2],radius,alpha,alpha0;
4566 const double *p0=i+1<nbOfLevsInVec?begin:third;
4567 const double *p1=i+1<nbOfLevsInVec?end:begin;
4568 const double *p2=i+1<nbOfLevsInVec?third:end;
4569 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4570 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]);
4571 double angle=acos(cosangle/(radius*radius));
4572 tmp->rotate(end,0,angle);
4573 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4579 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4580 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4581 * \return newCoords new coords filled by this method.
4583 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4586 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4587 int oldNbOfNodes=getNumberOfNodes();
4588 int nbOf1DCells=mesh1D->getNumberOfCells();
4590 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4591 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4592 int nbOfLevsInVec=nbOf1DCells+1;
4593 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4594 double *retPtr=ret->getPointer();
4595 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4596 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4597 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4598 tmp->setCoords(tmp2);
4599 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4600 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4601 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4602 for(int i=1;i<nbOfLevsInVec;i++)
4604 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4605 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4606 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4607 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4608 tmp->translate(vec);
4609 double tmp3[2],radius,alpha,alpha0;
4610 const double *p0=i+1<nbOfLevsInVec?begin:third;
4611 const double *p1=i+1<nbOfLevsInVec?end:begin;
4612 const double *p2=i+1<nbOfLevsInVec?third:end;
4613 double vecPlane[3]={
4614 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4615 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4616 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4618 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4621 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4622 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4623 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4625 double c2=cos(asin(s2));
4627 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4628 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4629 {-vec2[1]*s2, vec2[0]*s2, c2}
4631 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]};
4632 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]};
4633 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]};
4634 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4635 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]);
4636 double angle=acos(cosangle/(radius*radius));
4637 tmp->rotate(end,vecPlane,angle);
4640 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4646 * This method is private because not easy to use for end user. This method is const contrary to
4647 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4648 * the coords sorted slice by slice.
4649 * \param isQuad specifies presence of quadratic cells.
4651 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4653 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4654 int nbOf2DCells=getNumberOfCells();
4655 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4656 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4657 const int *conn=_nodal_connec->getConstPointer();
4658 const int *connI=_nodal_connec_index->getConstPointer();
4659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4661 newConnI->alloc(nbOf3DCells+1,1);
4662 int *newConnIPtr=newConnI->getPointer();
4664 std::vector<int> newc;
4665 for(int j=0;j<nbOf2DCells;j++)
4667 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4668 *newConnIPtr++=(int)newc.size();
4670 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4671 int *newConnPtr=newConn->getPointer();
4672 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4673 newConnIPtr=newConnI->getPointer();
4674 for(int iz=0;iz<nbOf1DCells;iz++)
4677 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4678 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4680 int icell=(int)(iter-newc.begin());
4681 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4684 *newConnPtr=(*iter)+iz*deltaPerLev;
4689 *newConnPtr=(*iter);
4692 ret->setConnectivity(newConn,newConnI,true);
4693 ret->setCoords(getCoords());
4698 * Checks if \a this mesh is constituted by only quadratic cells.
4699 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4700 * \throw If the coordinates array is not set.
4701 * \throw If the nodal connectivity of cells is not defined.
4703 bool MEDCouplingUMesh::isFullyQuadratic() const
4705 checkFullyDefined();
4707 int nbOfCells=getNumberOfCells();
4708 for(int i=0;i<nbOfCells && ret;i++)
4710 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4711 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4712 ret=cm.isQuadratic();
4718 * Checks if \a this mesh includes any quadratic cell.
4719 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4720 * \throw If the coordinates array is not set.
4721 * \throw If the nodal connectivity of cells is not defined.
4723 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4725 checkFullyDefined();
4727 int nbOfCells=getNumberOfCells();
4728 for(int i=0;i<nbOfCells && !ret;i++)
4730 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4731 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4732 ret=cm.isQuadratic();
4738 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4739 * this mesh, it remains unchanged.
4740 * \throw If the coordinates array is not set.
4741 * \throw If the nodal connectivity of cells is not defined.
4743 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4745 checkFullyDefined();
4746 int nbOfCells=getNumberOfCells();
4748 const int *iciptr=_nodal_connec_index->getConstPointer();
4749 for(int i=0;i<nbOfCells;i++)
4751 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4752 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4753 if(cm.isQuadratic())
4755 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4756 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4757 if(!cml.isDynamic())
4758 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4760 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4767 const int *icptr=_nodal_connec->getConstPointer();
4768 newConn->alloc(getMeshLength()-delta,1);
4769 newConnI->alloc(nbOfCells+1,1);
4770 int *ocptr=newConn->getPointer();
4771 int *ociptr=newConnI->getPointer();
4774 for(int i=0;i<nbOfCells;i++,ociptr++)
4776 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4777 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4778 if(!cm.isQuadratic())
4780 _types.insert(type);
4781 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4782 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4786 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4787 _types.insert(typel);
4788 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4789 int newNbOfNodes=cml.getNumberOfNodes();
4791 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4792 *ocptr++=(int)typel;
4793 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4794 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4797 setConnectivity(newConn,newConnI,false);
4801 * This method converts all linear cell in \a this to quadratic one.
4802 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4803 * 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)
4804 * 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.
4805 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4806 * end of the existing coordinates.
4808 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4809 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4810 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4812 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4814 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4816 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4818 DataArrayInt *conn=0,*connI=0;
4819 DataArrayDouble *coords=0;
4820 std::set<INTERP_KERNEL::NormalizedCellType> types;
4821 checkFullyDefined();
4822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4823 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4824 int meshDim=getMeshDimension();
4825 switch(conversionType)
4831 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4832 connSafe=conn; connISafe=connI; coordsSafe=coords;
4835 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4836 connSafe=conn; connISafe=connI; coordsSafe=coords;
4839 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4840 connSafe=conn; connISafe=connI; coordsSafe=coords;
4843 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4851 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4852 connSafe=conn; connISafe=connI; coordsSafe=coords;
4855 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4856 connSafe=conn; connISafe=connI; coordsSafe=coords;
4859 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4860 connSafe=conn; connISafe=connI; coordsSafe=coords;
4863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4870 setConnectivity(connSafe,connISafe,false);
4872 setCoords(coordsSafe);
4877 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4878 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4879 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4881 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4883 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4887 int nbOfCells=getNumberOfCells();
4888 int nbOfNodes=getNumberOfNodes();
4889 const int *cPtr=_nodal_connec->getConstPointer();
4890 const int *icPtr=_nodal_connec_index->getConstPointer();
4891 int lastVal=0,offset=nbOfNodes;
4892 for(int i=0;i<nbOfCells;i++,icPtr++)
4894 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4895 if(type==INTERP_KERNEL::NORM_SEG2)
4897 types.insert(INTERP_KERNEL::NORM_SEG3);
4898 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4899 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4900 newConn->pushBackSilent(offset++);
4902 newConnI->pushBackSilent(lastVal);
4903 ret->pushBackSilent(i);
4908 lastVal+=(icPtr[1]-icPtr[0]);
4909 newConnI->pushBackSilent(lastVal);
4910 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4913 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4914 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4918 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
4920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4924 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4925 DataArrayInt *conn1D=0,*conn1DI=0;
4926 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4927 DataArrayDouble *coordsTmp=0;
4928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4929 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4930 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4931 const int *c1DPtr=conn1D->begin();
4932 const int *c1DIPtr=conn1DI->begin();
4933 int nbOfCells=getNumberOfCells();
4934 const int *cPtr=_nodal_connec->getConstPointer();
4935 const int *icPtr=_nodal_connec_index->getConstPointer();
4937 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4939 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4940 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4941 if(!cm.isQuadratic())
4943 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4944 types.insert(typ2); newConn->pushBackSilent(typ2);
4945 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4946 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4947 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4948 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4949 newConnI->pushBackSilent(lastVal);
4950 ret->pushBackSilent(i);
4955 lastVal+=(icPtr[1]-icPtr[0]);
4956 newConnI->pushBackSilent(lastVal);
4957 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4960 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4965 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4966 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4967 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4969 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4973 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4974 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4977 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4980 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4986 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4987 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4988 DataArrayInt *conn1D=0,*conn1DI=0;
4989 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4990 DataArrayDouble *coordsTmp=0;
4991 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4992 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4994 const int *c1DPtr=conn1D->begin();
4995 const int *c1DIPtr=conn1DI->begin();
4996 int nbOfCells=getNumberOfCells();
4997 const int *cPtr=_nodal_connec->getConstPointer();
4998 const int *icPtr=_nodal_connec_index->getConstPointer();
4999 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5000 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5002 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5003 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5004 if(!cm.isQuadratic())
5006 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5007 types.insert(typ2); newConn->pushBackSilent(typ2);
5008 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5009 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5010 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5011 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5012 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5013 newConnI->pushBackSilent(lastVal);
5014 ret->pushBackSilent(i);
5019 lastVal+=(icPtr[1]-icPtr[0]);
5020 newConnI->pushBackSilent(lastVal);
5021 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5024 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5025 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5030 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5031 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5032 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5034 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5037 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5038 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5041 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5043 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5044 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5045 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5046 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5052 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5053 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5054 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5055 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5056 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5059 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5061 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5062 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5063 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5064 int nbOfCells=getNumberOfCells();
5065 const int *cPtr=_nodal_connec->getConstPointer();
5066 const int *icPtr=_nodal_connec_index->getConstPointer();
5067 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5068 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5070 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5071 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5072 if(!cm.isQuadratic())
5074 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5075 if(typ2==INTERP_KERNEL::NORM_ERROR)
5077 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5078 throw INTERP_KERNEL::Exception(oss.str().c_str());
5080 types.insert(typ2); newConn->pushBackSilent(typ2);
5081 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5082 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5083 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5084 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5086 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5087 int tmpPos=newConn->getNumberOfTuples();
5088 newConn->pushBackSilent(nodeId2);
5089 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5091 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5092 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5093 newConnI->pushBackSilent(lastVal);
5094 ret->pushBackSilent(i);
5099 lastVal+=(icPtr[1]-icPtr[0]);
5100 newConnI->pushBackSilent(lastVal);
5101 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5106 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5107 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5108 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5109 int *c=newConn->getPointer();
5110 const int *cI(newConnI->begin());
5111 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5112 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5113 offset=coordsTmp2Safe->getNumberOfTuples();
5114 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5115 c[cI[(*elt)+1]-1]+=offset;
5116 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5121 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5122 * so that the number of cells remains the same. Quadratic faces are converted to
5123 * polygons. This method works only for 2D meshes in
5124 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5125 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5126 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5127 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5128 * a polylinized edge constituting the input polygon.
5129 * \throw If the coordinates array is not set.
5130 * \throw If the nodal connectivity of cells is not defined.
5131 * \throw If \a this->getMeshDimension() != 2.
5132 * \throw If \a this->getSpaceDimension() != 2.
5134 void MEDCouplingUMesh::tessellate2D(double eps)
5136 checkFullyDefined();
5137 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5138 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5139 double epsa=fabs(eps);
5140 if(epsa<std::numeric_limits<double>::min())
5141 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 !");
5142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5144 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5146 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5147 revDesc1=0; revDescIndx1=0;
5148 mDesc->tessellate2DCurve(eps);
5149 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5150 setCoords(mDesc->getCoords());
5154 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5155 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5156 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5157 * a sub-divided edge.
5158 * \throw If the coordinates array is not set.
5159 * \throw If the nodal connectivity of cells is not defined.
5160 * \throw If \a this->getMeshDimension() != 1.
5161 * \throw If \a this->getSpaceDimension() != 2.
5163 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5165 checkFullyDefined();
5166 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5167 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5168 double epsa=fabs(eps);
5169 if(epsa<std::numeric_limits<double>::min())
5170 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 !");
5171 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5172 int nbCells=getNumberOfCells();
5173 int nbNodes=getNumberOfNodes();
5174 const int *conn=_nodal_connec->getConstPointer();
5175 const int *connI=_nodal_connec_index->getConstPointer();
5176 const double *coords=_coords->getConstPointer();
5177 std::vector<double> addCoo;
5178 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5180 newConnI->alloc(nbCells+1,1);
5181 int *newConnIPtr=newConnI->getPointer();
5184 INTERP_KERNEL::Node *tmp2[3];
5185 std::set<INTERP_KERNEL::NormalizedCellType> types;
5186 for(int i=0;i<nbCells;i++,newConnIPtr++)
5188 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5189 if(cm.isQuadratic())
5190 {//assert(connI[i+1]-connI[i]-1==3)
5191 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5192 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5193 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5194 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5195 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5198 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5199 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5201 newConnIPtr[1]=(int)newConn.size();
5205 types.insert(INTERP_KERNEL::NORM_SEG2);
5206 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5207 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5208 newConnIPtr[1]=newConnIPtr[0]+3;
5213 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5214 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5215 newConnIPtr[1]=newConnIPtr[0]+3;
5218 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5221 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5223 newConnArr->alloc((int)newConn.size(),1);
5224 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5225 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5226 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5227 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5228 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5229 std::copy(addCoo.begin(),addCoo.end(),work);
5230 DataArrayDouble::SetArrayIn(newCoords,_coords);
5235 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5236 * In addition, returns an array mapping new cells to old ones. <br>
5237 * This method typically increases the number of cells in \a this mesh
5238 * but the number of nodes remains \b unchanged.
5239 * That's why the 3D splitting policies
5240 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5241 * \param [in] policy - specifies a pattern used for splitting.
5242 * The semantic of \a policy is:
5243 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5244 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5245 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5246 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5247 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5248 * an id of old cell producing it. The caller is to delete this array using
5249 * decrRef() as it is no more needed.
5250 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5251 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5252 * and \a this->getMeshDimension() != 3.
5253 * \throw If \a policy is not one of the four discussed above.
5254 * \throw If the nodal connectivity of cells is not defined.
5255 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5257 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5262 return simplexizePol0();
5264 return simplexizePol1();
5265 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5266 return simplexizePlanarFace5();
5267 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5268 return simplexizePlanarFace6();
5270 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)");
5275 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5276 * - 1D: INTERP_KERNEL::NORM_SEG2
5277 * - 2D: INTERP_KERNEL::NORM_TRI3
5278 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5280 * This method is useful for users that need to use P1 field services as
5281 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5282 * All these methods need mesh support containing only simplex cells.
5283 * \return bool - \c true if there are only simplex cells in \a this mesh.
5284 * \throw If the coordinates array is not set.
5285 * \throw If the nodal connectivity of cells is not defined.
5286 * \throw If \a this->getMeshDimension() < 1.
5288 bool MEDCouplingUMesh::areOnlySimplexCells() const
5290 checkFullyDefined();
5291 int mdim=getMeshDimension();
5292 if(mdim<1 || mdim>3)
5293 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5294 int nbCells=getNumberOfCells();
5295 const int *conn=_nodal_connec->getConstPointer();
5296 const int *connI=_nodal_connec_index->getConstPointer();
5297 for(int i=0;i<nbCells;i++)
5299 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5307 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5309 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5311 checkConnectivityFullyDefined();
5312 if(getMeshDimension()!=2)
5313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5314 int nbOfCells=getNumberOfCells();
5315 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5316 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5317 ret->alloc(nbOfCells+nbOfCutCells,1);
5318 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5319 int *retPt=ret->getPointer();
5320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5322 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5323 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5324 int *pt=newConn->getPointer();
5325 int *ptI=newConnI->getPointer();
5327 const int *oldc=_nodal_connec->getConstPointer();
5328 const int *ci=_nodal_connec_index->getConstPointer();
5329 for(int i=0;i<nbOfCells;i++,ci++)
5331 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5333 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5334 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5335 pt=std::copy(tmp,tmp+8,pt);
5344 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5345 ptI[1]=ptI[0]+ci[1]-ci[0];
5350 _nodal_connec->decrRef();
5351 _nodal_connec=newConn.retn();
5352 _nodal_connec_index->decrRef();
5353 _nodal_connec_index=newConnI.retn();
5360 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5362 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5364 checkConnectivityFullyDefined();
5365 if(getMeshDimension()!=2)
5366 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5367 int nbOfCells=getNumberOfCells();
5368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5369 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5370 ret->alloc(nbOfCells+nbOfCutCells,1);
5371 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5372 int *retPt=ret->getPointer();
5373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5375 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5376 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5377 int *pt=newConn->getPointer();
5378 int *ptI=newConnI->getPointer();
5380 const int *oldc=_nodal_connec->getConstPointer();
5381 const int *ci=_nodal_connec_index->getConstPointer();
5382 for(int i=0;i<nbOfCells;i++,ci++)
5384 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5386 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5387 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5388 pt=std::copy(tmp,tmp+8,pt);
5397 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5398 ptI[1]=ptI[0]+ci[1]-ci[0];
5403 _nodal_connec->decrRef();
5404 _nodal_connec=newConn.retn();
5405 _nodal_connec_index->decrRef();
5406 _nodal_connec_index=newConnI.retn();
5413 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5415 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5417 checkConnectivityFullyDefined();
5418 if(getMeshDimension()!=3)
5419 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5420 int nbOfCells=getNumberOfCells();
5421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5422 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5423 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5424 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5425 int *retPt=ret->getPointer();
5426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5428 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5429 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5430 int *pt=newConn->getPointer();
5431 int *ptI=newConnI->getPointer();
5433 const int *oldc=_nodal_connec->getConstPointer();
5434 const int *ci=_nodal_connec_index->getConstPointer();
5435 for(int i=0;i<nbOfCells;i++,ci++)
5437 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5439 for(int j=0;j<5;j++,pt+=5,ptI++)
5441 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5442 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];
5449 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5450 ptI[1]=ptI[0]+ci[1]-ci[0];
5455 _nodal_connec->decrRef();
5456 _nodal_connec=newConn.retn();
5457 _nodal_connec_index->decrRef();
5458 _nodal_connec_index=newConnI.retn();
5465 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5467 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5469 checkConnectivityFullyDefined();
5470 if(getMeshDimension()!=3)
5471 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5472 int nbOfCells=getNumberOfCells();
5473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5474 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5475 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5476 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5477 int *retPt=ret->getPointer();
5478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5480 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5481 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5482 int *pt=newConn->getPointer();
5483 int *ptI=newConnI->getPointer();
5485 const int *oldc=_nodal_connec->getConstPointer();
5486 const int *ci=_nodal_connec_index->getConstPointer();
5487 for(int i=0;i<nbOfCells;i++,ci++)
5489 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5491 for(int j=0;j<6;j++,pt+=5,ptI++)
5493 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5494 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];
5501 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5502 ptI[1]=ptI[0]+ci[1]-ci[0];
5507 _nodal_connec->decrRef();
5508 _nodal_connec=newConn.retn();
5509 _nodal_connec_index->decrRef();
5510 _nodal_connec_index=newConnI.retn();
5517 * 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.
5518 * This method completly ignore coordinates.
5519 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5520 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5521 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5522 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5524 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5526 checkFullyDefined();
5527 if(getMeshDimension()!=2)
5528 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5529 int nbOfCells=getNumberOfCells();
5530 int *connI=_nodal_connec_index->getPointer();
5532 for(int i=0;i<nbOfCells;i++,connI++)
5534 int offset=descIndex[i];
5535 int nbOfEdges=descIndex[i+1]-offset;
5537 bool ddirect=desc[offset+nbOfEdges-1]>0;
5538 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5539 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5540 for(int j=0;j<nbOfEdges;j++)
5542 bool direct=desc[offset+j]>0;
5543 int edgeId=std::abs(desc[offset+j])-1;
5544 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5546 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5547 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5548 int ref2=direct?id1:id2;
5551 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5552 newConnLgth+=nbOfSubNodes-1;
5557 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5558 throw INTERP_KERNEL::Exception(oss.str().c_str());
5563 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5566 newConnLgth++;//+1 is for cell type
5567 connI[1]=newConnLgth;
5570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5571 newConn->alloc(newConnLgth,1);
5572 int *work=newConn->getPointer();
5573 for(int i=0;i<nbOfCells;i++)
5575 *work++=INTERP_KERNEL::NORM_POLYGON;
5576 int offset=descIndex[i];
5577 int nbOfEdges=descIndex[i+1]-offset;
5578 for(int j=0;j<nbOfEdges;j++)
5580 bool direct=desc[offset+j]>0;
5581 int edgeId=std::abs(desc[offset+j])-1;
5583 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5586 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5587 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5588 work=std::copy(it,it+nbOfSubNodes-1,work);
5592 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5595 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5599 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5600 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5601 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5602 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5603 * so it can be useful to call mergeNodes() before calling this method.
5604 * \throw If \a this->getMeshDimension() <= 1.
5605 * \throw If the coordinates array is not set.
5606 * \throw If the nodal connectivity of cells is not defined.
5608 void MEDCouplingUMesh::convertDegeneratedCells()
5610 checkFullyDefined();
5611 if(getMeshDimension()<=1)
5612 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5613 int nbOfCells=getNumberOfCells();
5616 int initMeshLgth=getMeshLength();
5617 int *conn=_nodal_connec->getPointer();
5618 int *index=_nodal_connec_index->getPointer();
5622 for(int i=0;i<nbOfCells;i++)
5624 lgthOfCurCell=index[i+1]-posOfCurCell;
5625 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5627 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5628 conn+newPos+1,newLgth);
5629 conn[newPos]=newType;
5631 posOfCurCell=index[i+1];
5634 if(newPos!=initMeshLgth)
5635 _nodal_connec->reAlloc(newPos);
5640 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5641 * A cell is considered to be oriented correctly if an angle between its
5642 * normal vector and a given vector is less than \c PI / \c 2.
5643 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5645 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5647 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5648 * is not cleared before filling in.
5649 * \throw If \a this->getMeshDimension() != 2.
5650 * \throw If \a this->getSpaceDimension() != 3.
5652 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5653 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5655 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5657 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5658 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5659 int nbOfCells=getNumberOfCells();
5660 const int *conn=_nodal_connec->getConstPointer();
5661 const int *connI=_nodal_connec_index->getConstPointer();
5662 const double *coordsPtr=_coords->getConstPointer();
5663 for(int i=0;i<nbOfCells;i++)
5665 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5666 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5668 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5669 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5676 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5677 * considered to be oriented correctly if an angle between its normal vector and a
5678 * given vector is less than \c PI / \c 2.
5679 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5681 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5683 * \throw If \a this->getMeshDimension() != 2.
5684 * \throw If \a this->getSpaceDimension() != 3.
5686 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5687 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5689 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5691 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5692 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5693 int nbOfCells=getNumberOfCells();
5694 int *conn=_nodal_connec->getPointer();
5695 const int *connI=_nodal_connec_index->getConstPointer();
5696 const double *coordsPtr=_coords->getConstPointer();
5697 bool isModified=false;
5698 for(int i=0;i<nbOfCells;i++)
5700 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5701 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5703 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5704 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5709 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5710 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5711 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5715 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5716 std::vector<int> tmp0(sz-1),tmp1(sz);
5717 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5718 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5719 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5720 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5726 _nodal_connec->declareAsNew();
5731 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5732 * oriented facets. The normal vector of the facet should point out of the cell.
5733 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5734 * is not cleared before filling in.
5735 * \throw If \a this->getMeshDimension() != 3.
5736 * \throw If \a this->getSpaceDimension() != 3.
5737 * \throw If the coordinates array is not set.
5738 * \throw If the nodal connectivity of cells is not defined.
5740 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5741 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5743 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5745 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5746 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5747 int nbOfCells=getNumberOfCells();
5748 const int *conn=_nodal_connec->getConstPointer();
5749 const int *connI=_nodal_connec_index->getConstPointer();
5750 const double *coordsPtr=_coords->getConstPointer();
5751 for(int i=0;i<nbOfCells;i++)
5753 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5754 if(type==INTERP_KERNEL::NORM_POLYHED)
5756 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5763 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5765 * \throw If \a this->getMeshDimension() != 3.
5766 * \throw If \a this->getSpaceDimension() != 3.
5767 * \throw If the coordinates array is not set.
5768 * \throw If the nodal connectivity of cells is not defined.
5769 * \throw If the reparation fails.
5771 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5772 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5773 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5775 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5777 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5778 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5779 int nbOfCells=getNumberOfCells();
5780 int *conn=_nodal_connec->getPointer();
5781 const int *connI=_nodal_connec_index->getConstPointer();
5782 const double *coordsPtr=_coords->getConstPointer();
5783 for(int i=0;i<nbOfCells;i++)
5785 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5786 if(type==INTERP_KERNEL::NORM_POLYHED)
5790 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5791 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5793 catch(INTERP_KERNEL::Exception& e)
5795 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5796 throw INTERP_KERNEL::Exception(oss.str().c_str());
5804 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5805 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5806 * according to which the first facet of the cell should be oriented to have the normal vector
5807 * pointing out of cell.
5808 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5809 * cells. The caller is to delete this array using decrRef() as it is no more
5811 * \throw If \a this->getMeshDimension() != 3.
5812 * \throw If \a this->getSpaceDimension() != 3.
5813 * \throw If the coordinates array is not set.
5814 * \throw If the nodal connectivity of cells is not defined.
5816 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5817 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5818 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5820 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5822 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5823 if(getMeshDimension()!=3)
5824 throw INTERP_KERNEL::Exception(msg);
5825 int spaceDim=getSpaceDimension();
5827 throw INTERP_KERNEL::Exception(msg);
5829 int nbOfCells=getNumberOfCells();
5830 int *conn=_nodal_connec->getPointer();
5831 const int *connI=_nodal_connec_index->getConstPointer();
5832 const double *coo=getCoords()->getConstPointer();
5833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5834 for(int i=0;i<nbOfCells;i++)
5836 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5837 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5839 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5841 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5842 cells->pushBackSilent(i);
5846 return cells.retn();
5850 * This method is a faster method to correct orientation of all 3D cells in \a this.
5851 * 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.
5852 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5854 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5855 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5857 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5859 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5860 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5861 int nbOfCells=getNumberOfCells();
5862 int *conn=_nodal_connec->getPointer();
5863 const int *connI=_nodal_connec_index->getConstPointer();
5864 const double *coordsPtr=_coords->getConstPointer();
5865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5866 for(int i=0;i<nbOfCells;i++)
5868 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5871 case INTERP_KERNEL::NORM_TETRA4:
5873 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5875 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5876 ret->pushBackSilent(i);
5880 case INTERP_KERNEL::NORM_PYRA5:
5882 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5884 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5885 ret->pushBackSilent(i);
5889 case INTERP_KERNEL::NORM_PENTA6:
5890 case INTERP_KERNEL::NORM_HEXA8:
5891 case INTERP_KERNEL::NORM_HEXGP12:
5893 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5895 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5896 ret->pushBackSilent(i);
5900 case INTERP_KERNEL::NORM_POLYHED:
5902 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5904 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5905 ret->pushBackSilent(i);
5910 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 !");
5918 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5919 * If it is not the case an exception will be thrown.
5920 * This method is fast because the first cell of \a this is used to compute the plane.
5921 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5922 * \param pos output of size at least 3 used to store a point owned of searched plane.
5924 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5926 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5927 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5928 const int *conn=_nodal_connec->getConstPointer();
5929 const int *connI=_nodal_connec_index->getConstPointer();
5930 const double *coordsPtr=_coords->getConstPointer();
5931 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5932 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5936 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5937 * cells. Currently cells of the following types are treated:
5938 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5939 * For a cell of other type an exception is thrown.
5940 * Space dimension of a 2D mesh can be either 2 or 3.
5941 * The Edge Ratio of a cell \f$t\f$ is:
5942 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5943 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5944 * the smallest edge lengths of \f$t\f$.
5945 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5946 * cells and one time, lying on \a this mesh. The caller is to delete this
5947 * field using decrRef() as it is no more needed.
5948 * \throw If the coordinates array is not set.
5949 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5950 * \throw If the connectivity data array has more than one component.
5951 * \throw If the connectivity data array has a named component.
5952 * \throw If the connectivity index data array has more than one component.
5953 * \throw If the connectivity index data array has a named component.
5954 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5955 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5956 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5958 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5961 int spaceDim=getSpaceDimension();
5962 int meshDim=getMeshDimension();
5963 if(spaceDim!=2 && spaceDim!=3)
5964 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5965 if(meshDim!=2 && meshDim!=3)
5966 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5967 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5969 int nbOfCells=getNumberOfCells();
5970 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5971 arr->alloc(nbOfCells,1);
5972 double *pt=arr->getPointer();
5973 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5974 const int *conn=_nodal_connec->getConstPointer();
5975 const int *connI=_nodal_connec_index->getConstPointer();
5976 const double *coo=_coords->getConstPointer();
5978 for(int i=0;i<nbOfCells;i++,pt++)
5980 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5983 case INTERP_KERNEL::NORM_TRI3:
5985 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5986 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5989 case INTERP_KERNEL::NORM_QUAD4:
5991 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5992 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5995 case INTERP_KERNEL::NORM_TETRA4:
5997 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5998 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6002 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6004 conn+=connI[i+1]-connI[i];
6006 ret->setName("EdgeRatio");
6007 ret->synchronizeTimeWithSupport();
6012 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6013 * cells. Currently cells of the following types are treated:
6014 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6015 * For a cell of other type an exception is thrown.
6016 * Space dimension of a 2D mesh can be either 2 or 3.
6017 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6018 * cells and one time, lying on \a this mesh. The caller is to delete this
6019 * field using decrRef() as it is no more needed.
6020 * \throw If the coordinates array is not set.
6021 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6022 * \throw If the connectivity data array has more than one component.
6023 * \throw If the connectivity data array has a named component.
6024 * \throw If the connectivity index data array has more than one component.
6025 * \throw If the connectivity index data array has a named component.
6026 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6027 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6028 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6030 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6033 int spaceDim=getSpaceDimension();
6034 int meshDim=getMeshDimension();
6035 if(spaceDim!=2 && spaceDim!=3)
6036 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6037 if(meshDim!=2 && meshDim!=3)
6038 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6039 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6041 int nbOfCells=getNumberOfCells();
6042 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6043 arr->alloc(nbOfCells,1);
6044 double *pt=arr->getPointer();
6045 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6046 const int *conn=_nodal_connec->getConstPointer();
6047 const int *connI=_nodal_connec_index->getConstPointer();
6048 const double *coo=_coords->getConstPointer();
6050 for(int i=0;i<nbOfCells;i++,pt++)
6052 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6055 case INTERP_KERNEL::NORM_TRI3:
6057 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6058 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6061 case INTERP_KERNEL::NORM_QUAD4:
6063 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6064 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6067 case INTERP_KERNEL::NORM_TETRA4:
6069 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6070 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6074 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6076 conn+=connI[i+1]-connI[i];
6078 ret->setName("AspectRatio");
6079 ret->synchronizeTimeWithSupport();
6084 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6085 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6086 * treated: INTERP_KERNEL::NORM_QUAD4.
6087 * For a cell of other type an exception is thrown.
6088 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6089 * cells and one time, lying on \a this mesh. The caller is to delete this
6090 * field using decrRef() as it is no more needed.
6091 * \throw If the coordinates array is not set.
6092 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6093 * \throw If the connectivity data array has more than one component.
6094 * \throw If the connectivity data array has a named component.
6095 * \throw If the connectivity index data array has more than one component.
6096 * \throw If the connectivity index data array has a named component.
6097 * \throw If \a this->getMeshDimension() != 2.
6098 * \throw If \a this->getSpaceDimension() != 3.
6099 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6101 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6104 int spaceDim=getSpaceDimension();
6105 int meshDim=getMeshDimension();
6107 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6110 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6112 int nbOfCells=getNumberOfCells();
6113 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6114 arr->alloc(nbOfCells,1);
6115 double *pt=arr->getPointer();
6116 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6117 const int *conn=_nodal_connec->getConstPointer();
6118 const int *connI=_nodal_connec_index->getConstPointer();
6119 const double *coo=_coords->getConstPointer();
6121 for(int i=0;i<nbOfCells;i++,pt++)
6123 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6126 case INTERP_KERNEL::NORM_QUAD4:
6128 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6129 *pt=INTERP_KERNEL::quadWarp(tmp);
6133 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6135 conn+=connI[i+1]-connI[i];
6137 ret->setName("Warp");
6138 ret->synchronizeTimeWithSupport();
6144 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6145 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6146 * treated: INTERP_KERNEL::NORM_QUAD4.
6147 * For a cell of other type an exception is thrown.
6148 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6149 * cells and one time, lying on \a this mesh. The caller is to delete this
6150 * field using decrRef() as it is no more needed.
6151 * \throw If the coordinates array is not set.
6152 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6153 * \throw If the connectivity data array has more than one component.
6154 * \throw If the connectivity data array has a named component.
6155 * \throw If the connectivity index data array has more than one component.
6156 * \throw If the connectivity index data array has a named component.
6157 * \throw If \a this->getMeshDimension() != 2.
6158 * \throw If \a this->getSpaceDimension() != 3.
6159 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6161 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6164 int spaceDim=getSpaceDimension();
6165 int meshDim=getMeshDimension();
6167 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6169 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6170 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6172 int nbOfCells=getNumberOfCells();
6173 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6174 arr->alloc(nbOfCells,1);
6175 double *pt=arr->getPointer();
6176 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6177 const int *conn=_nodal_connec->getConstPointer();
6178 const int *connI=_nodal_connec_index->getConstPointer();
6179 const double *coo=_coords->getConstPointer();
6181 for(int i=0;i<nbOfCells;i++,pt++)
6183 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6186 case INTERP_KERNEL::NORM_QUAD4:
6188 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6189 *pt=INTERP_KERNEL::quadSkew(tmp);
6193 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6195 conn+=connI[i+1]-connI[i];
6197 ret->setName("Skew");
6198 ret->synchronizeTimeWithSupport();
6203 * This method aggregate the bbox of each cell and put it into bbox parameter.
6205 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6207 * \throw If \a this is not fully set (coordinates and connectivity).
6208 * \throw If a cell in \a this has no valid nodeId.
6210 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6212 checkFullyDefined();
6213 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6214 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6215 double *bbox(ret->getPointer());
6216 for(int i=0;i<nbOfCells*spaceDim;i++)
6218 bbox[2*i]=std::numeric_limits<double>::max();
6219 bbox[2*i+1]=-std::numeric_limits<double>::max();
6221 const double *coordsPtr(_coords->getConstPointer());
6222 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6223 for(int i=0;i<nbOfCells;i++)
6225 int offset=connI[i]+1;
6226 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6227 for(int j=0;j<nbOfNodesForCell;j++)
6229 int nodeId=conn[offset+j];
6230 if(nodeId>=0 && nodeId<nbOfNodes)
6232 for(int k=0;k<spaceDim;k++)
6234 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6235 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6242 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6243 throw INTERP_KERNEL::Exception(oss.str().c_str());
6251 namespace ParaMEDMEMImpl
6256 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6257 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6266 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6267 bool operator() (const int& pos) { return _conn[pos]==_val; }
6277 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6278 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6279 * \a this is composed in cell types.
6280 * The returned array is of size 3*n where n is the number of different types present in \a this.
6281 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6282 * This parameter is kept only for compatibility with other methode listed above.
6284 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6286 checkConnectivityFullyDefined();
6287 const int *conn=_nodal_connec->getConstPointer();
6288 const int *connI=_nodal_connec_index->getConstPointer();
6289 const int *work=connI;
6290 int nbOfCells=getNumberOfCells();
6291 std::size_t n=getAllTypes().size();
6292 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6293 std::set<INTERP_KERNEL::NormalizedCellType> types;
6294 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6296 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6297 if(types.find(typ)!=types.end())
6299 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6300 oss << " is not contiguous !";
6301 throw INTERP_KERNEL::Exception(oss.str().c_str());
6305 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6306 ret[3*i+1]=(int)std::distance(work,work2);
6313 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6314 * only for types cell, type node is not managed.
6315 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6316 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6317 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6318 * If 2 or more same geometric type is in \a code and exception is thrown too.
6320 * This method firstly checks
6321 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6322 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6323 * an exception is thrown too.
6325 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6326 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6327 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6329 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6332 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6333 std::size_t sz=code.size();
6336 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6337 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6339 bool isNoPflUsed=true;
6340 for(std::size_t i=0;i<n;i++)
6341 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6343 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6345 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6347 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6353 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6355 if(types.size()==_types.size())
6358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6360 int *retPtr=ret->getPointer();
6361 const int *connI=_nodal_connec_index->getConstPointer();
6362 const int *conn=_nodal_connec->getConstPointer();
6363 int nbOfCells=getNumberOfCells();
6366 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6368 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6369 int offset=(int)std::distance(connI,i);
6370 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6371 int nbOfCellsOfCurType=(int)std::distance(i,j);
6372 if(code[3*kk+2]==-1)
6373 for(int k=0;k<nbOfCellsOfCurType;k++)
6377 int idInIdsPerType=code[3*kk+2];
6378 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6380 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6383 zePfl->checkAllocated();
6384 if(zePfl->getNumberOfComponents()==1)
6386 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6388 if(*k>=0 && *k<nbOfCellsOfCurType)
6389 *retPtr=(*k)+offset;
6392 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6393 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6394 throw INTERP_KERNEL::Exception(oss.str().c_str());
6399 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6402 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6406 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6407 oss << " should be in [0," << idsPerType.size() << ") !";
6408 throw INTERP_KERNEL::Exception(oss.str().c_str());
6417 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6418 * 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.
6419 * 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.
6420 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6422 * \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.
6423 * \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,
6424 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6425 * \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.
6426 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6427 * \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
6429 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6432 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6433 if(profile->getNumberOfComponents()!=1)
6434 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6435 checkConnectivityFullyDefined();
6436 const int *conn=_nodal_connec->getConstPointer();
6437 const int *connI=_nodal_connec_index->getConstPointer();
6438 int nbOfCells=getNumberOfCells();
6439 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6440 std::vector<int> typeRangeVals(1);
6441 for(const int *i=connI;i!=connI+nbOfCells;)
6443 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6444 if(std::find(types.begin(),types.end(),curType)!=types.end())
6446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6448 types.push_back(curType);
6449 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6450 typeRangeVals.push_back((int)std::distance(connI,i));
6453 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6454 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6459 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6460 code.resize(3*nbOfCastsFinal);
6461 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6462 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6463 for(int i=0;i<nbOfCastsFinal;i++)
6465 int castId=castsPresent->getIJ(i,0);
6466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6467 idsInPflPerType2.push_back(tmp3);
6468 code[3*i]=(int)types[castId];
6469 code[3*i+1]=tmp3->getNumberOfTuples();
6470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6471 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6473 tmp4->copyStringInfoFrom(*profile);
6474 idsPerType2.push_back(tmp4);
6475 code[3*i+2]=(int)idsPerType2.size()-1;
6482 std::size_t sz2=idsInPflPerType2.size();
6483 idsInPflPerType.resize(sz2);
6484 for(std::size_t i=0;i<sz2;i++)
6486 DataArrayInt *locDa=idsInPflPerType2[i];
6488 idsInPflPerType[i]=locDa;
6490 std::size_t sz=idsPerType2.size();
6491 idsPerType.resize(sz);
6492 for(std::size_t i=0;i<sz;i++)
6494 DataArrayInt *locDa=idsPerType2[i];
6496 idsPerType[i]=locDa;
6501 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6502 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6503 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6504 * 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.
6506 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6508 checkFullyDefined();
6509 nM1LevMesh->checkFullyDefined();
6510 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6511 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6512 if(_coords!=nM1LevMesh->getCoords())
6513 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6516 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6518 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6519 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6520 tmp->setConnectivity(tmp0,tmp1);
6521 tmp->renumberCells(ret0->getConstPointer(),false);
6522 revDesc=tmp->getNodalConnectivity();
6523 revDescIndx=tmp->getNodalConnectivityIndex();
6524 DataArrayInt *ret=0;
6525 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6528 ret->getMaxValue(tmp2);
6530 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6531 throw INTERP_KERNEL::Exception(oss.str().c_str());
6536 revDescIndx->incrRef();
6539 meshnM1Old2New=ret0;
6544 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6545 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6546 * in "Old to New" mode.
6547 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6548 * this array using decrRef() as it is no more needed.
6549 * \throw If the nodal connectivity of cells is not defined.
6551 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6553 checkConnectivityFullyDefined();
6554 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6555 renumberCells(ret->getConstPointer(),false);
6560 * This methods checks that cells are sorted by their types.
6561 * This method makes asumption (no check) that connectivity is correctly set before calling.
6563 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6565 checkFullyDefined();
6566 const int *conn=_nodal_connec->getConstPointer();
6567 const int *connI=_nodal_connec_index->getConstPointer();
6568 int nbOfCells=getNumberOfCells();
6569 std::set<INTERP_KERNEL::NormalizedCellType> types;
6570 for(const int *i=connI;i!=connI+nbOfCells;)
6572 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6573 if(types.find(curType)!=types.end())
6575 types.insert(curType);
6576 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6582 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6583 * The geometric type order is specified by MED file.
6585 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6587 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6589 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6593 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6594 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6595 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6596 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6598 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6600 checkFullyDefined();
6601 const int *conn=_nodal_connec->getConstPointer();
6602 const int *connI=_nodal_connec_index->getConstPointer();
6603 int nbOfCells=getNumberOfCells();
6607 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6608 for(const int *i=connI;i!=connI+nbOfCells;)
6610 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6611 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6612 if(isTypeExists!=orderEnd)
6614 int pos=(int)std::distance(orderBg,isTypeExists);
6618 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6622 if(sg.find(curType)==sg.end())
6624 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6635 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6636 * 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
6637 * 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'.
6639 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6641 checkConnectivityFullyDefined();
6642 int nbOfCells=getNumberOfCells();
6643 const int *conn=_nodal_connec->getConstPointer();
6644 const int *connI=_nodal_connec_index->getConstPointer();
6645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6647 tmpa->alloc(nbOfCells,1);
6648 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6649 tmpb->fillWithZero();
6650 int *tmp=tmpa->getPointer();
6651 int *tmp2=tmpb->getPointer();
6652 for(const int *i=connI;i!=connI+nbOfCells;i++)
6654 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6657 int pos=(int)std::distance(orderBg,where);
6659 tmp[std::distance(connI,i)]=pos;
6663 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6664 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6665 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6666 throw INTERP_KERNEL::Exception(oss.str().c_str());
6669 nbPerType=tmpb.retn();
6674 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6676 * \return a new object containing the old to new correspondance.
6678 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6680 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6682 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6686 * 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.
6687 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6688 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6689 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6691 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6693 DataArrayInt *nbPerType=0;
6694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6695 nbPerType->decrRef();
6696 return tmpa->buildPermArrPerLevel();
6700 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6701 * The number of cells remains unchanged after the call of this method.
6702 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6703 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6705 * \return the array giving the correspondance old to new.
6707 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6709 checkFullyDefined();
6711 const int *conn=_nodal_connec->getConstPointer();
6712 const int *connI=_nodal_connec_index->getConstPointer();
6713 int nbOfCells=getNumberOfCells();
6714 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6715 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6716 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6718 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6719 types.push_back(curType);
6720 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6722 DataArrayInt *ret=DataArrayInt::New();
6723 ret->alloc(nbOfCells,1);
6724 int *retPtr=ret->getPointer();
6725 std::fill(retPtr,retPtr+nbOfCells,-1);
6727 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6729 for(const int *i=connI;i!=connI+nbOfCells;i++)
6730 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6731 retPtr[std::distance(connI,i)]=newCellId++;
6733 renumberCells(retPtr,false);
6738 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6739 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6740 * This method makes asumption that connectivity is correctly set before calling.
6742 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6744 checkConnectivityFullyDefined();
6745 const int *conn=_nodal_connec->getConstPointer();
6746 const int *connI=_nodal_connec_index->getConstPointer();
6747 int nbOfCells=getNumberOfCells();
6748 std::vector<MEDCouplingUMesh *> ret;
6749 for(const int *i=connI;i!=connI+nbOfCells;)
6751 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6752 int beginCellId=(int)std::distance(connI,i);
6753 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6754 int endCellId=(int)std::distance(connI,i);
6755 int sz=endCellId-beginCellId;
6756 int *cells=new int[sz];
6757 for(int j=0;j<sz;j++)
6758 cells[j]=beginCellId+j;
6759 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6767 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6768 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6769 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6771 * \return a newly allocated instance, that the caller must manage.
6772 * \throw If \a this contains more than one geometric type.
6773 * \throw If the nodal connectivity of \a this is not fully defined.
6774 * \throw If the internal data is not coherent.
6776 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6778 checkConnectivityFullyDefined();
6779 if(_types.size()!=1)
6780 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6781 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6782 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6783 ret->setCoords(getCoords());
6784 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6788 retC->setNodalConnectivity(c);
6792 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6795 DataArrayInt *c=0,*ci=0;
6796 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6798 retD->setNodalConnectivity(cs,cis);
6803 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6805 checkConnectivityFullyDefined();
6806 if(_types.size()!=1)
6807 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6808 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6809 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6812 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6813 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6814 throw INTERP_KERNEL::Exception(oss.str().c_str());
6816 int nbCells=getNumberOfCells();
6818 int nbNodesPerCell=(int)cm.getNumberOfNodes();
6819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6820 int *outPtr=connOut->getPointer();
6821 const int *conn=_nodal_connec->begin();
6822 const int *connI=_nodal_connec_index->begin();
6824 for(int i=0;i<nbCells;i++,connI++)
6826 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6827 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6830 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 << ") !";
6831 throw INTERP_KERNEL::Exception(oss.str().c_str());
6834 return connOut.retn();
6837 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6839 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6840 checkConnectivityFullyDefined();
6841 if(_types.size()!=1)
6842 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6843 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6845 throw INTERP_KERNEL::Exception(msg0);
6846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6847 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6848 int *cp(c->getPointer()),*cip(ci->getPointer());
6849 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6851 for(int i=0;i<nbCells;i++,cip++,incip++)
6853 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6854 int delta(stop-strt);
6857 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6858 cp=std::copy(incp+strt,incp+stop,cp);
6860 throw INTERP_KERNEL::Exception(msg0);
6863 throw INTERP_KERNEL::Exception(msg0);
6864 cip[1]=cip[0]+delta;
6866 nodalConn=c.retn(); nodalConnIndex=ci.retn();
6870 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6871 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6872 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6873 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6874 * are not used here to avoid the build of big permutation array.
6876 * \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
6877 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6878 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6879 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6880 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6881 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6882 * \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
6883 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6885 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6886 DataArrayInt *&szOfCellGrpOfSameType,
6887 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6889 std::vector<const MEDCouplingUMesh *> ms2;
6890 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6893 (*it)->checkConnectivityFullyDefined();
6897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6898 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6899 int meshDim=ms2[0]->getMeshDimension();
6900 std::vector<const MEDCouplingUMesh *> m1ssm;
6901 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6903 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6904 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6907 ret1->alloc(0,1); ret2->alloc(0,1);
6908 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6910 if(meshDim!=(*it)->getMeshDimension())
6911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6912 if(refCoo!=(*it)->getCoords())
6913 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6914 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6915 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6916 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6917 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6919 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6920 m1ssmSingleAuto.push_back(singleCell);
6921 m1ssmSingle.push_back(singleCell);
6922 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6925 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6927 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6928 for(std::size_t i=0;i<m1ssm.size();i++)
6929 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6930 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6931 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6932 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6937 * This method returns a newly created DataArrayInt instance.
6938 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6940 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6942 checkFullyDefined();
6943 const int *conn=_nodal_connec->getConstPointer();
6944 const int *connIndex=_nodal_connec_index->getConstPointer();
6945 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6946 for(const int *w=begin;w!=end;w++)
6947 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6948 ret->pushBackSilent(*w);
6953 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6954 * are in [0:getNumberOfCells())
6956 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6958 checkFullyDefined();
6959 const int *conn=_nodal_connec->getConstPointer();
6960 const int *connI=_nodal_connec_index->getConstPointer();
6961 int nbOfCells=getNumberOfCells();
6962 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6963 int *tmp=new int[nbOfCells];
6964 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6967 for(const int *i=connI;i!=connI+nbOfCells;i++)
6968 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6969 tmp[std::distance(connI,i)]=j++;
6971 DataArrayInt *ret=DataArrayInt::New();
6972 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6973 ret->copyStringInfoFrom(*da);
6974 int *retPtr=ret->getPointer();
6975 const int *daPtr=da->getConstPointer();
6976 int nbOfElems=da->getNbOfElems();
6977 for(int k=0;k<nbOfElems;k++)
6978 retPtr[k]=tmp[daPtr[k]];
6984 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6985 * This method \b works \b for mesh sorted by type.
6986 * cells whose ids is in 'idsPerGeoType' array.
6987 * This method conserves coords and name of mesh.
6989 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6991 std::vector<int> code=getDistributionOfTypes();
6992 std::size_t nOfTypesInThis=code.size()/3;
6993 int sz=0,szOfType=0;
6994 for(std::size_t i=0;i<nOfTypesInThis;i++)
6999 szOfType=code[3*i+1];
7001 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7002 if(*work<0 || *work>=szOfType)
7004 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7005 oss << ". It should be in [0," << szOfType << ") !";
7006 throw INTERP_KERNEL::Exception(oss.str().c_str());
7008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7009 int *idsPtr=idsTokeep->getPointer();
7011 for(std::size_t i=0;i<nOfTypesInThis;i++)
7014 for(int j=0;j<code[3*i+1];j++)
7017 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7018 offset+=code[3*i+1];
7020 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7021 ret->copyTinyInfoFrom(this);
7026 * This method returns a vector of size 'this->getNumberOfCells()'.
7027 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7029 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7031 int ncell=getNumberOfCells();
7032 std::vector<bool> ret(ncell);
7033 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7034 const int *c=getNodalConnectivity()->getConstPointer();
7035 for(int i=0;i<ncell;i++)
7037 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7038 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7039 ret[i]=cm.isQuadratic();
7045 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7047 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7049 if(other->getType()!=UNSTRUCTURED)
7050 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7051 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7052 return MergeUMeshes(this,otherC);
7056 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7057 * computed by averaging coordinates of cell nodes, so this method is not a right
7058 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7059 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7060 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7061 * components. The caller is to delete this array using decrRef() as it is
7063 * \throw If the coordinates array is not set.
7064 * \throw If the nodal connectivity of cells is not defined.
7065 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7067 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7069 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7070 int spaceDim=getSpaceDimension();
7071 int nbOfCells=getNumberOfCells();
7072 ret->alloc(nbOfCells,spaceDim);
7073 ret->copyStringInfoFrom(*getCoords());
7074 double *ptToFill=ret->getPointer();
7075 const int *nodal=_nodal_connec->getConstPointer();
7076 const int *nodalI=_nodal_connec_index->getConstPointer();
7077 const double *coor=_coords->getConstPointer();
7078 for(int i=0;i<nbOfCells;i++)
7080 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7081 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7088 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7089 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7091 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7092 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7094 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7095 * \throw If \a this is not fully defined (coordinates and connectivity)
7096 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7098 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7100 checkFullyDefined();
7101 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7102 int spaceDim=getSpaceDimension();
7103 int nbOfCells=getNumberOfCells();
7104 int nbOfNodes=getNumberOfNodes();
7105 ret->alloc(nbOfCells,spaceDim);
7106 double *ptToFill=ret->getPointer();
7107 const int *nodal=_nodal_connec->getConstPointer();
7108 const int *nodalI=_nodal_connec_index->getConstPointer();
7109 const double *coor=_coords->getConstPointer();
7110 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7112 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7113 std::fill(ptToFill,ptToFill+spaceDim,0.);
7114 if(type!=INTERP_KERNEL::NORM_POLYHED)
7116 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7118 if(*conn>=0 && *conn<nbOfNodes)
7119 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7122 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7123 throw INTERP_KERNEL::Exception(oss.str().c_str());
7126 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7127 if(nbOfNodesInCell>0)
7128 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7131 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7132 throw INTERP_KERNEL::Exception(oss.str().c_str());
7137 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7139 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7141 if(*it>=0 && *it<nbOfNodes)
7142 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7145 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7146 throw INTERP_KERNEL::Exception(oss.str().c_str());
7150 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7153 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7154 throw INTERP_KERNEL::Exception(oss.str().c_str());
7162 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7163 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7164 * are specified via an array of cell ids.
7165 * \warning Validity of the specified cell ids is not checked!
7166 * Valid range is [ 0, \a this->getNumberOfCells() ).
7167 * \param [in] begin - an array of cell ids of interest.
7168 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7169 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7170 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7171 * caller is to delete this array using decrRef() as it is no more needed.
7172 * \throw If the coordinates array is not set.
7173 * \throw If the nodal connectivity of cells is not defined.
7175 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7176 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7178 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7180 DataArrayDouble *ret=DataArrayDouble::New();
7181 int spaceDim=getSpaceDimension();
7182 int nbOfTuple=(int)std::distance(begin,end);
7183 ret->alloc(nbOfTuple,spaceDim);
7184 double *ptToFill=ret->getPointer();
7185 double *tmp=new double[spaceDim];
7186 const int *nodal=_nodal_connec->getConstPointer();
7187 const int *nodalI=_nodal_connec_index->getConstPointer();
7188 const double *coor=_coords->getConstPointer();
7189 for(const int *w=begin;w!=end;w++)
7191 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7192 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7200 * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7201 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7202 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7203 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7204 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7206 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7207 * \throw If spaceDim!=3 or meshDim!=2.
7208 * \throw If connectivity of \a this is invalid.
7209 * \throw If connectivity of a cell in \a this points to an invalid node.
7211 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7213 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7214 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7215 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7216 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7217 ret->alloc(nbOfCells,4);
7218 double *retPtr(ret->getPointer());
7219 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7220 const double *coor(_coords->begin());
7221 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7223 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7224 if(nodalI[1]-nodalI[0]>=3)
7226 for(int j=0;j<3;j++)
7228 int nodeId(nodal[nodalI[0]+1+j]);
7229 if(nodeId>=0 && nodeId<nbOfNodes)
7230 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7233 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7234 throw INTERP_KERNEL::Exception(oss.str().c_str());
7240 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7241 throw INTERP_KERNEL::Exception(oss.str().c_str());
7243 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7244 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7250 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7253 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7256 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7257 da->checkAllocated();
7258 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7260 int nbOfTuples=da->getNumberOfTuples();
7261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7263 c->alloc(2*nbOfTuples,1);
7264 cI->alloc(nbOfTuples+1,1);
7265 int *cp=c->getPointer();
7266 int *cip=cI->getPointer();
7268 for(int i=0;i<nbOfTuples;i++)
7270 *cp++=INTERP_KERNEL::NORM_POINT1;
7274 ret->setConnectivity(c,cI,true);
7278 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7279 * Cells and nodes of
7280 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7281 * \param [in] mesh1 - the first mesh.
7282 * \param [in] mesh2 - the second mesh.
7283 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7284 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7285 * is no more needed.
7286 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7287 * \throw If the coordinates array is not set in none of the meshes.
7288 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7289 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7291 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7293 std::vector<const MEDCouplingUMesh *> tmp(2);
7294 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7295 return MergeUMeshes(tmp);
7299 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7300 * Cells and nodes of
7301 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7302 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7303 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7304 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7305 * is no more needed.
7306 * \throw If \a a.size() == 0.
7307 * \throw If \a a[ *i* ] == NULL.
7308 * \throw If the coordinates array is not set in none of the meshes.
7309 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7310 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7312 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7314 std::size_t sz=a.size();
7316 return MergeUMeshesLL(a);
7317 for(std::size_t ii=0;ii<sz;ii++)
7320 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7321 throw INTERP_KERNEL::Exception(oss.str().c_str());
7323 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7324 std::vector< const MEDCouplingUMesh * > aa(sz);
7326 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7328 const MEDCouplingUMesh *cur=a[i];
7329 const DataArrayDouble *coo=cur->getCoords();
7331 spaceDim=coo->getNumberOfComponents();
7334 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7335 for(std::size_t i=0;i<sz;i++)
7337 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7340 return MergeUMeshesLL(aa);
7345 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7349 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7350 int meshDim=(*it)->getMeshDimension();
7351 int nbOfCells=(*it)->getNumberOfCells();
7352 int meshLgth=(*it++)->getMeshLength();
7353 for(;it!=a.end();it++)
7355 if(meshDim!=(*it)->getMeshDimension())
7356 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7357 nbOfCells+=(*it)->getNumberOfCells();
7358 meshLgth+=(*it)->getMeshLength();
7360 std::vector<const MEDCouplingPointSet *> aps(a.size());
7361 std::copy(a.begin(),a.end(),aps.begin());
7362 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7363 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7364 ret->setCoords(pts);
7365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7366 c->alloc(meshLgth,1);
7367 int *cPtr=c->getPointer();
7368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7369 cI->alloc(nbOfCells+1,1);
7370 int *cIPtr=cI->getPointer();
7374 for(it=a.begin();it!=a.end();it++)
7376 int curNbOfCell=(*it)->getNumberOfCells();
7377 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7378 const int *curC=(*it)->_nodal_connec->getConstPointer();
7379 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7380 for(int j=0;j<curNbOfCell;j++)
7382 const int *src=curC+curCI[j];
7384 for(;src!=curC+curCI[j+1];src++,cPtr++)
7392 offset+=curCI[curNbOfCell];
7393 offset2+=(*it)->getNumberOfNodes();
7396 ret->setConnectivity(c,cI,true);
7403 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7404 * dimension and sharing the node coordinates array.
7405 * All cells of the first mesh precede all cells of the second mesh
7406 * within the result mesh.
7407 * \param [in] mesh1 - the first mesh.
7408 * \param [in] mesh2 - the second mesh.
7409 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7410 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7411 * is no more needed.
7412 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7413 * \throw If the meshes do not share the node coordinates array.
7414 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7415 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7417 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7419 std::vector<const MEDCouplingUMesh *> tmp(2);
7420 tmp[0]=mesh1; tmp[1]=mesh2;
7421 return MergeUMeshesOnSameCoords(tmp);
7425 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7426 * dimension and sharing the node coordinates array.
7427 * All cells of the *i*-th mesh precede all cells of the
7428 * (*i*+1)-th mesh within the result mesh.
7429 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7430 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7431 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7432 * is no more needed.
7433 * \throw If \a a.size() == 0.
7434 * \throw If \a a[ *i* ] == NULL.
7435 * \throw If the meshes do not share the node coordinates array.
7436 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7437 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7439 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7442 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7443 for(std::size_t ii=0;ii<meshes.size();ii++)
7446 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7447 throw INTERP_KERNEL::Exception(oss.str().c_str());
7449 const DataArrayDouble *coords=meshes.front()->getCoords();
7450 int meshDim=meshes.front()->getMeshDimension();
7451 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7453 int meshIndexLgth=0;
7454 for(;iter!=meshes.end();iter++)
7456 if(coords!=(*iter)->getCoords())
7457 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7458 if(meshDim!=(*iter)->getMeshDimension())
7459 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7460 meshLgth+=(*iter)->getMeshLength();
7461 meshIndexLgth+=(*iter)->getNumberOfCells();
7463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7464 nodal->alloc(meshLgth,1);
7465 int *nodalPtr=nodal->getPointer();
7466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7467 nodalIndex->alloc(meshIndexLgth+1,1);
7468 int *nodalIndexPtr=nodalIndex->getPointer();
7470 for(iter=meshes.begin();iter!=meshes.end();iter++)
7472 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7473 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7474 int nbOfCells=(*iter)->getNumberOfCells();
7475 int meshLgth2=(*iter)->getMeshLength();
7476 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7477 if(iter!=meshes.begin())
7478 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7480 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7483 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7484 ret->setName("merge");
7485 ret->setMeshDimension(meshDim);
7486 ret->setConnectivity(nodal,nodalIndex,true);
7487 ret->setCoords(coords);
7492 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7493 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7494 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7495 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7496 * New" mode are returned for each input mesh.
7497 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7498 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7499 * valid values [0,1,2], see zipConnectivityTraducer().
7500 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7501 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7502 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7504 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7505 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7506 * is no more needed.
7507 * \throw If \a meshes.size() == 0.
7508 * \throw If \a meshes[ *i* ] == NULL.
7509 * \throw If the meshes do not share the node coordinates array.
7510 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7511 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7512 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7513 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7515 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7517 //All checks are delegated to MergeUMeshesOnSameCoords
7518 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7519 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7520 corr.resize(meshes.size());
7521 std::size_t nbOfMeshes=meshes.size();
7523 const int *o2nPtr=o2n->getConstPointer();
7524 for(std::size_t i=0;i<nbOfMeshes;i++)
7526 DataArrayInt *tmp=DataArrayInt::New();
7527 int curNbOfCells=meshes[i]->getNumberOfCells();
7528 tmp->alloc(curNbOfCells,1);
7529 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7530 offset+=curNbOfCells;
7531 tmp->setName(meshes[i]->getName().c_str());
7538 * Makes all given meshes share the nodal connectivity array. The common connectivity
7539 * array is created by concatenating the connectivity arrays of all given meshes. All
7540 * the given meshes must be of the same space dimension but dimension of cells **can
7541 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7542 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7543 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7544 * \param [in,out] meshes - a vector of meshes to update.
7545 * \throw If any of \a meshes is NULL.
7546 * \throw If the coordinates array is not set in any of \a meshes.
7547 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7548 * \throw If \a meshes are of different space dimension.
7550 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7552 std::size_t sz=meshes.size();
7555 std::vector< const DataArrayDouble * > coords(meshes.size());
7556 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7557 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7561 (*it)->checkConnectivityFullyDefined();
7562 const DataArrayDouble *coo=(*it)->getCoords();
7567 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7568 oss << " has no coordinate array defined !";
7569 throw INTERP_KERNEL::Exception(oss.str().c_str());
7574 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7575 oss << " is null !";
7576 throw INTERP_KERNEL::Exception(oss.str().c_str());
7579 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7580 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7581 int offset=(*it)->getNumberOfNodes();
7582 (*it++)->setCoords(res);
7583 for(;it!=meshes.end();it++)
7585 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7586 (*it)->setCoords(res);
7587 (*it)->shiftNodeNumbersInConn(offset);
7588 offset+=oldNumberOfNodes;
7593 * Merges nodes coincident with a given precision within all given meshes that share
7594 * the nodal connectivity array. The given meshes **can be of different** mesh
7595 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7596 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7597 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7598 * \param [in,out] meshes - a vector of meshes to update.
7599 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7600 * \throw If any of \a meshes is NULL.
7601 * \throw If the \a meshes do not share the same node coordinates array.
7602 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7604 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7608 std::set<const DataArrayDouble *> s;
7609 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7612 s.insert((*it)->getCoords());
7615 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 !";
7616 throw INTERP_KERNEL::Exception(oss.str().c_str());
7621 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 !";
7622 throw INTERP_KERNEL::Exception(oss.str().c_str());
7624 const DataArrayDouble *coo=*(s.begin());
7628 DataArrayInt *comm,*commI;
7629 coo->findCommonTuples(eps,-1,comm,commI);
7630 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7631 int oldNbOfNodes=coo->getNumberOfTuples();
7633 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7634 if(oldNbOfNodes==newNbOfNodes)
7636 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7637 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7639 (*it)->renumberNodesInConn(o2n->getConstPointer());
7640 (*it)->setCoords(newCoords);
7645 * 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.
7646 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7647 * \param isQuad specifies the policy of connectivity.
7648 * @ret in/out parameter in which the result will be append
7650 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7652 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7653 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7654 ret.push_back(cm.getExtrudedType());
7655 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7658 case INTERP_KERNEL::NORM_POINT1:
7660 ret.push_back(connBg[1]);
7661 ret.push_back(connBg[1]+nbOfNodesPerLev);
7664 case INTERP_KERNEL::NORM_SEG2:
7666 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7667 ret.insert(ret.end(),conn,conn+4);
7670 case INTERP_KERNEL::NORM_SEG3:
7672 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7673 ret.insert(ret.end(),conn,conn+8);
7676 case INTERP_KERNEL::NORM_QUAD4:
7678 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7679 ret.insert(ret.end(),conn,conn+8);
7682 case INTERP_KERNEL::NORM_TRI3:
7684 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7685 ret.insert(ret.end(),conn,conn+6);
7688 case INTERP_KERNEL::NORM_TRI6:
7690 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,
7691 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7692 ret.insert(ret.end(),conn,conn+15);
7695 case INTERP_KERNEL::NORM_QUAD8:
7698 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7699 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7700 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7702 ret.insert(ret.end(),conn,conn+20);
7705 case INTERP_KERNEL::NORM_POLYGON:
7707 std::back_insert_iterator< std::vector<int> > ii(ret);
7708 std::copy(connBg+1,connEnd,ii);
7710 std::reverse_iterator<const int *> rConnBg(connEnd);
7711 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7712 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7713 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7714 for(std::size_t i=0;i<nbOfRadFaces;i++)
7717 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7718 std::copy(conn,conn+4,ii);
7723 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7728 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7730 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7732 double v[3]={0.,0.,0.};
7733 std::size_t sz=std::distance(begin,end);
7736 for(std::size_t i=0;i<sz;i++)
7738 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];
7739 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7740 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7742 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7746 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7748 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7750 std::vector<std::pair<int,int> > edges;
7751 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7752 const int *bgFace=begin;
7753 for(std::size_t i=0;i<nbOfFaces;i++)
7755 const int *endFace=std::find(bgFace+1,end,-1);
7756 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7757 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7759 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7760 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7762 edges.push_back(p1);
7766 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7770 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7772 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7774 double vec0[3],vec1[3];
7775 std::size_t sz=std::distance(begin,end);
7777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7778 int nbOfNodes=(int)sz/2;
7779 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7780 const double *pt0=coords+3*begin[0];
7781 const double *pt1=coords+3*begin[nbOfNodes];
7782 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7783 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7786 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7788 std::size_t sz=std::distance(begin,end);
7789 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7790 std::size_t nbOfNodes(sz/2);
7791 std::copy(begin,end,(int *)tmp);
7792 for(std::size_t j=1;j<nbOfNodes;j++)
7794 begin[j]=tmp[nbOfNodes-j];
7795 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7799 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7801 std::size_t sz=std::distance(begin,end);
7803 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7804 double vec0[3],vec1[3];
7805 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7806 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];
7807 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;
7810 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7812 std::size_t sz=std::distance(begin,end);
7814 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7816 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7817 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7818 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7822 * 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 )
7823 * 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
7826 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7827 * \param [in] coords the coordinates with nb of components exactly equal to 3
7828 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7829 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7830 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7832 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
7834 int nbFaces=std::count(begin+1,end,-1)+1;
7835 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7836 double *vPtr=v->getPointer();
7837 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7838 double *pPtr=p->getPointer();
7839 const int *stFaceConn=begin+1;
7840 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7842 const int *endFaceConn=std::find(stFaceConn,end,-1);
7843 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7844 stFaceConn=endFaceConn+1;
7846 pPtr=p->getPointer(); vPtr=v->getPointer();
7847 DataArrayInt *comm1=0,*commI1=0;
7848 v->findCommonTuples(eps,-1,comm1,commI1);
7849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7850 const int *comm1Ptr=comm1->getConstPointer();
7851 const int *commI1Ptr=commI1->getConstPointer();
7852 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7853 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7855 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7856 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7857 mm->finishInsertingCells();
7859 for(int i=0;i<nbOfGrps1;i++)
7861 int vecId=comm1Ptr[commI1Ptr[i]];
7862 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7863 DataArrayInt *comm2=0,*commI2=0;
7864 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7866 const int *comm2Ptr=comm2->getConstPointer();
7867 const int *commI2Ptr=commI2->getConstPointer();
7868 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7869 for(int j=0;j<nbOfGrps2;j++)
7871 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7873 res->insertAtTheEnd(begin,end);
7874 res->pushBackSilent(-1);
7878 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7880 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7881 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7882 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7883 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7886 const int *idsNodePtr=idsNode->getConstPointer();
7887 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];
7888 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7889 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7890 if(std::abs(norm)>eps)
7892 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7893 mm3->rotate(center,vec,angle);
7895 mm3->changeSpaceDimension(2);
7896 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7897 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7898 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7899 int nbOfCells=mm4->getNumberOfCells();
7900 for(int k=0;k<nbOfCells;k++)
7903 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7904 res->pushBackSilent(idsNodePtr[*work]);
7905 res->pushBackSilent(-1);
7910 res->popBackSilent();
7914 * 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
7915 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7917 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7918 * \param [in] coords coordinates expected to have 3 components.
7919 * \param [in] begin start of the nodal connectivity of the face.
7920 * \param [in] end end of the nodal connectivity (excluded) of the face.
7921 * \param [out] v the normalized vector of size 3
7922 * \param [out] p the pos of plane
7924 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7926 std::size_t nbPoints=std::distance(begin,end);
7928 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7929 double vec[3]={0.,0.,0.};
7931 bool refFound=false;
7932 for(;j<nbPoints-1 && !refFound;j++)
7934 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7935 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7936 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7937 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7941 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7944 for(std::size_t i=j;i<nbPoints-1;i++)
7947 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7948 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7949 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7950 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7953 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7954 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];
7955 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7958 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7959 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7963 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7967 * This method tries to obtain a well oriented polyhedron.
7968 * If the algorithm fails, an exception will be thrown.
7970 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7972 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7973 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7974 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7976 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7977 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7978 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7980 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7983 std::size_t smthChanged=0;
7984 for(std::size_t i=0;i<nbOfFaces;i++)
7986 endFace=std::find(bgFace+1,end,-1);
7987 nbOfEdgesInFace=std::distance(bgFace,endFace);
7991 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7993 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7994 std::pair<int,int> p2(p1.second,p1.first);
7995 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7996 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7997 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8002 std::reverse(bgFace+1,endFace);
8003 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8005 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8006 std::pair<int,int> p2(p1.second,p1.first);
8007 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8008 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8009 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8010 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8011 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8012 if(it!=edgesOK.end())
8015 edgesFinished.push_back(p1);
8018 edgesOK.push_back(p1);
8025 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8027 if(!edgesOK.empty())
8028 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8029 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8030 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8032 for(std::size_t i=0;i<nbOfFaces;i++)
8034 endFace=std::find(bgFace+1,end,-1);
8035 std::reverse(bgFace+1,endFace);
8042 * This method makes the assumption spacedimension == meshdimension == 2.
8043 * This method works only for linear cells.
8045 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8047 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8049 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8051 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8053 int nbOfNodesExpected=m->getNumberOfNodes();
8054 if(m->getNumberOfCells()!=nbOfNodesExpected)
8055 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8057 const int *n2oPtr=n2o->getConstPointer();
8058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8059 m->getReverseNodalConnectivity(revNodal,revNodalI);
8060 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8061 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8062 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8064 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
8065 if(nbOfNodesExpected<1)
8068 int prevNode=nodalPtr[nodalIPtr[0]+1];
8069 *work++=n2oPtr[prevNode];
8070 for(int i=1;i<nbOfNodesExpected;i++)
8072 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8074 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8075 conn.erase(prevNode);
8078 int curNode=*(conn.begin());
8079 *work++=n2oPtr[curNode];
8080 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8081 shar.erase(prevCell);
8084 prevCell=*(shar.begin());
8088 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8091 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8094 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8100 * This method makes the assumption spacedimension == meshdimension == 3.
8101 * This method works only for linear cells.
8103 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8105 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8107 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8108 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8109 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8110 const int *conn=m->getNodalConnectivity()->getConstPointer();
8111 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8112 int nbOfCells=m->getNumberOfCells();
8113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8114 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8117 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8118 for(int i=1;i<nbOfCells;i++)
8121 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8127 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8128 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8130 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8134 for(int i=0;i<nbOfNodesInCell;i++)
8135 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8136 else if(spaceDim==2)
8138 for(int i=0;i<nbOfNodesInCell;i++)
8140 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8145 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8148 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8150 int nbOfCells=getNumberOfCells();
8152 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8153 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};
8154 ofs << " <" << getVTKDataSetType() << ">\n";
8155 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8156 ofs << " <PointData>\n" << pointData << std::endl;
8157 ofs << " </PointData>\n";
8158 ofs << " <CellData>\n" << cellData << std::endl;
8159 ofs << " </CellData>\n";
8160 ofs << " <Points>\n";
8161 if(getSpaceDimension()==3)
8162 _coords->writeVTK(ofs,8,"Points",byteData);
8165 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8166 coo->writeVTK(ofs,8,"Points",byteData);
8168 ofs << " </Points>\n";
8169 ofs << " <Cells>\n";
8170 const int *cPtr=_nodal_connec->getConstPointer();
8171 const int *cIPtr=_nodal_connec_index->getConstPointer();
8172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8176 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8177 int szFaceOffsets=0,szConn=0;
8178 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8181 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8184 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8185 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8189 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8190 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8191 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8192 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8193 w4=std::copy(c.begin(),c.end(),w4);
8196 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8197 types->writeVTK(ofs,8,"UInt8","types",byteData);
8198 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8199 if(szFaceOffsets!=0)
8200 {//presence of Polyhedra
8201 connectivity->reAlloc(szConn);
8202 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8203 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8204 w1=faces->getPointer();
8205 for(int i=0;i<nbOfCells;i++)
8206 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8208 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8210 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8211 for(int j=0;j<nbFaces;j++)
8213 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8214 *w1++=(int)std::distance(w6,w5);
8215 w1=std::copy(w6,w5,w1);
8219 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8221 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8222 ofs << " </Cells>\n";
8223 ofs << " </Piece>\n";
8224 ofs << " </" << getVTKDataSetType() << ">\n";
8227 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8229 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8231 { stream << " Not set !"; return ; }
8232 stream << " Mesh dimension : " << _mesh_dim << ".";
8236 { stream << " No coordinates set !"; return ; }
8237 if(!_coords->isAllocated())
8238 { stream << " Coordinates set but not allocated !"; return ; }
8239 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8240 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8241 if(!_nodal_connec_index)
8242 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8243 if(!_nodal_connec_index->isAllocated())
8244 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8245 int lgth=_nodal_connec_index->getNumberOfTuples();
8246 int cpt=_nodal_connec_index->getNumberOfComponents();
8247 if(cpt!=1 || lgth<1)
8249 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8252 std::string MEDCouplingUMesh::getVTKDataSetType() const
8254 return std::string("UnstructuredGrid");
8258 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8259 * returns a result mesh constituted by polygons.
8260 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8261 * all nodes from m2.
8262 * The meshes should be in 2D space. In
8263 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8265 * \param [in] m1 - the first input mesh which is a partitioned object.
8266 * \param [in] m2 - the second input mesh which is a partition tool.
8267 * \param [in] eps - precision used to detect coincident mesh entities.
8268 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8269 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8270 * this array using decrRef() as it is no more needed.
8271 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8272 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8273 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8274 * any cell of \a m2. The caller is to delete this array using decrRef() as
8275 * it is no more needed.
8276 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8277 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8278 * is no more needed.
8279 * \throw If the coordinates array is not set in any of the meshes.
8280 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8281 * \throw If any of the meshes is not a 2D mesh in 2D space.
8283 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8284 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8286 m1->checkFullyDefined();
8287 m2->checkFullyDefined();
8288 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8289 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8291 // Step 1: compute all edge intersections (new nodes)
8292 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8293 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8294 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8295 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8296 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8297 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8298 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8299 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8300 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8301 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8303 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8305 // Step 2: re-order newly created nodes according to the ordering found in m2
8306 std::vector< std::vector<int> > intersectEdge2;
8307 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8308 subDiv2.clear(); dd5=0; dd6=0;
8311 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8312 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8313 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8314 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8316 // Step 4: Prepare final result:
8317 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8318 addCooDa->alloc((int)(addCoo.size())/2,2);
8319 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8320 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8321 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8322 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8323 std::vector<const DataArrayDouble *> coordss(4);
8324 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8325 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8326 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8331 ret->setConnectivity(conn,connI,true);
8332 ret->setCoords(coo);
8333 cellNb1=c1.retn(); cellNb2=c2.retn();
8339 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8340 * (newly created) nodes corresponding to the edge intersections.
8342 * @param[out] cr, crI connectivity of the resulting mesh
8343 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8344 * TODO: describe input parameters
8346 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8347 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8348 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8349 const std::vector<double>& addCoords,
8350 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8352 static const int SPACEDIM=2;
8353 const double *coo1=m1->getCoords()->getConstPointer();
8354 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8355 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8356 int offset1=m1->getNumberOfNodes();
8357 const double *coo2=m2->getCoords()->getConstPointer();
8358 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8359 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8360 int offset2=offset1+m2->getNumberOfNodes();
8361 int offset3=offset2+((int)addCoords.size())/2;
8362 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8363 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8364 // Here a BBTree on 2D-cells, not on segments:
8365 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8366 int ncell1=m1->getNumberOfCells();
8368 for(int i=0;i<ncell1;i++)
8370 std::vector<int> candidates2;
8371 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8372 std::map<INTERP_KERNEL::Node *,int> mapp;
8373 std::map<int,INTERP_KERNEL::Node *> mappRev;
8374 INTERP_KERNEL::QuadraticPolygon pol1;
8375 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8376 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8377 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8378 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8379 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8380 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8382 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
8383 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8384 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8385 for(it1.first();!it1.finished();it1.next())
8386 edges1.insert(it1.current()->getPtr());
8388 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8389 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8391 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8393 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8394 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8395 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8396 // pol2 is the new QP in the final merged result.
8397 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8398 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8401 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8403 pol1.initLocationsWithOther(pol2s[ii]);
8404 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8405 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8406 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8408 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8409 // by m2 but that we still want to keep in the final result.
8414 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8416 catch(INTERP_KERNEL::Exception& e)
8418 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();
8419 throw INTERP_KERNEL::Exception(oss.str().c_str());
8422 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8423 (*it).second->decrRef();
8428 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8429 * It builds the descending connectivity of the two meshes, and then using a binary tree
8430 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8431 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8433 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8434 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8435 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8436 std::vector<double>& addCoo,
8437 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8438 throw(INTERP_KERNEL::Exception)
8440 static const int SPACEDIM=2;
8441 // Build desc connectivity
8442 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8443 desc2=DataArrayInt::New();
8444 descIndx2=DataArrayInt::New();
8445 revDesc2=DataArrayInt::New();
8446 revDescIndx2=DataArrayInt::New();
8447 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8449 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8450 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8451 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8452 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8453 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8455 // Build BB tree of all edges in the tool mesh (second mesh)
8456 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8457 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8458 int nDescCell1=m1Desc->getNumberOfCells();
8459 int nDescCell2=m2Desc->getNumberOfCells();
8460 intersectEdge1.resize(nDescCell1);
8461 colinear2.resize(nDescCell2);
8462 subDiv2.resize(nDescCell2);
8463 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8465 std::vector<int> candidates1(1);
8466 int offset1=m1->getNumberOfNodes();
8467 int offset2=offset1+m2->getNumberOfNodes();
8468 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
8470 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8471 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8472 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8474 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8475 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8476 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8478 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8479 // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
8480 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8481 std::set<INTERP_KERNEL::Node *> nodes;
8482 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8483 std::size_t szz(nodes.size());
8484 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8485 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8486 for(std::size_t iii=0;iii<szz;iii++,itt++)
8487 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8488 // end of protection
8489 // Performs egde cutting:
8490 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8495 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8497 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8498 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8502 * This method performs the 2nd step of Partition of 2D mesh.
8503 * This method has 4 inputs :
8504 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8505 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8506 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
8507 * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
8508 * Nodes end up lying consecutively on a cutted edge.
8509 * \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.
8510 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
8511 * \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.
8512 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
8513 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
8515 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8516 const std::vector<double>& addCoo,
8517 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
8519 int offset1=m1->getNumberOfNodes();
8520 int ncell=m2->getNumberOfCells();
8521 const int *c=m2->getNodalConnectivity()->getConstPointer();
8522 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8523 const double *coo=m2->getCoords()->getConstPointer();
8524 const double *cooBis=m1->getCoords()->getConstPointer();
8525 int offset2=offset1+m2->getNumberOfNodes();
8526 intersectEdge.resize(ncell);
8527 for(int i=0;i<ncell;i++,cI++)
8529 const std::vector<int>& divs=subDiv[i];
8530 int nnode=cI[1]-cI[0]-1;
8531 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8532 std::map<INTERP_KERNEL::Node *, int> mapp22;
8533 for(int j=0;j<nnode;j++)
8535 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8536 int nnid=c[(*cI)+j+1];
8537 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8538 mapp22[nn]=nnid+offset1;
8540 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8541 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8542 ((*it).second.first)->decrRef();
8543 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8544 std::map<INTERP_KERNEL::Node *,int> mapp3;
8545 for(std::size_t j=0;j<divs.size();j++)
8548 INTERP_KERNEL::Node *tmp=0;
8550 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8552 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8554 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8558 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8559 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8566 * 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).
8567 * 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
8568 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8569 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8570 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8571 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8572 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8573 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8574 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8575 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8576 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8577 * \param [out] cut3DSuf input/output param.
8579 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8580 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8581 const int *desc, const int *descIndx,
8582 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8584 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8585 int nbOf3DSurfCell=(int)cut3DSurf.size();
8586 for(int i=0;i<nbOf3DSurfCell;i++)
8588 std::vector<int> res;
8589 int offset=descIndx[i];
8590 int nbOfSeg=descIndx[i+1]-offset;
8591 for(int j=0;j<nbOfSeg;j++)
8593 int edgeId=desc[offset+j];
8594 int status=cut3DCurve[edgeId];
8598 res.push_back(status);
8601 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8602 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8610 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8616 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8617 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8620 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8624 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8629 {// case when plane is on a multi colinear edge of a polyhedron
8630 if((int)res.size()==2*nbOfSeg)
8632 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8635 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8642 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8643 * 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).
8644 * 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
8645 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8646 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8647 * \param desc is the descending connectivity 3D->3DSurf
8648 * \param descIndx is the descending connectivity index 3D->3DSurf
8650 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8651 const int *desc, const int *descIndx,
8652 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8654 checkFullyDefined();
8655 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8657 const int *nodal3D=_nodal_connec->getConstPointer();
8658 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8659 int nbOfCells=getNumberOfCells();
8660 for(int i=0;i<nbOfCells;i++)
8662 std::map<int, std::set<int> > m;
8663 int offset=descIndx[i];
8664 int nbOfFaces=descIndx[i+1]-offset;
8667 for(int j=0;j<nbOfFaces;j++)
8669 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8670 if(p.first!=-1 && p.second!=-1)
8674 start=p.first; end=p.second;
8675 m[p.first].insert(p.second);
8676 m[p.second].insert(p.first);
8680 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8681 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8682 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8683 INTERP_KERNEL::NormalizedCellType cmsId;
8684 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8685 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8686 for(unsigned k=0;k<nbOfNodesSon;k++)
8688 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8689 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8696 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8700 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8701 const std::set<int>& s=(*it).second;
8702 std::set<int> s2; s2.insert(prev);
8704 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8707 int val=*s3.begin();
8708 conn.push_back(start);
8715 conn.push_back(end);
8718 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8719 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8720 cellIds->pushBackSilent(i);
8726 * 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
8727 * 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
8728 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8729 * 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
8730 * 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.
8732 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8734 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
8736 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8739 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8740 if(cm.getDimension()==2)
8742 const int *node=nodalConnBg+1;
8743 int startNode=*node++;
8744 double refX=coords[2*startNode];
8745 for(;node!=nodalConnEnd;node++)
8747 if(coords[2*(*node)]<refX)
8750 refX=coords[2*startNode];
8753 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8757 double angle0=-M_PI/2;
8762 double angleNext=0.;
8763 while(nextNode!=startNode)
8767 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8769 if(*node!=tmpOut.back() && *node!=prevNode)
8771 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8772 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8777 res=angle0-angleM+2.*M_PI;
8786 if(nextNode!=startNode)
8788 angle0=angleNext-M_PI;
8791 prevNode=tmpOut.back();
8792 tmpOut.push_back(nextNode);
8795 std::vector<int> tmp3(2*(sz-1));
8796 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8797 std::copy(nodalConnBg+1,nodalConnEnd,it);
8798 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8800 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8803 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8805 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8810 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8811 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8819 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8823 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8824 * 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.
8826 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8827 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8828 * \param [in,out] arr array in which the remove operation will be done.
8829 * \param [in,out] arrIndx array in the remove operation will modify
8830 * \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])
8831 * \return true if \b arr and \b arrIndx have been modified, false if not.
8833 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
8835 if(!arrIndx || !arr)
8836 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8837 if(offsetForRemoval<0)
8838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8839 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8840 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8841 int *arrIPtr=arrIndx->getPointer();
8844 const int *arrPtr=arr->getConstPointer();
8845 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8846 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8848 if(*arrIPtr-previousArrI>offsetForRemoval)
8850 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8852 if(s.find(*work)==s.end())
8853 arrOut.push_back(*work);
8856 previousArrI=*arrIPtr;
8857 *arrIPtr=(int)arrOut.size();
8859 if(arr->getNumberOfTuples()==(int)arrOut.size())
8861 arr->alloc((int)arrOut.size(),1);
8862 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8867 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8868 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8869 * The selection of extraction is done standardly in new2old format.
8870 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8872 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8873 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8874 * \param [in] arrIn arr origin array from which the extraction will be done.
8875 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8876 * \param [out] arrOut the resulting array
8877 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8878 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8880 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8881 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8883 if(!arrIn || !arrIndxIn)
8884 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8885 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8886 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8888 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8889 const int *arrInPtr=arrIn->getConstPointer();
8890 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8891 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8893 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8894 int maxSizeOfArr=arrIn->getNumberOfTuples();
8895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8897 arrIo->alloc((int)(sz+1),1);
8898 const int *idsIt=idsOfSelectBg;
8899 int *work=arrIo->getPointer();
8902 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8904 if(*idsIt>=0 && *idsIt<nbOfGrps)
8905 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8908 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8909 throw INTERP_KERNEL::Exception(oss.str().c_str());
8915 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8916 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8917 throw INTERP_KERNEL::Exception(oss.str().c_str());
8920 arro->alloc(lgth,1);
8921 work=arro->getPointer();
8922 idsIt=idsOfSelectBg;
8923 for(std::size_t i=0;i<sz;i++,idsIt++)
8925 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8926 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8929 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8930 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8931 throw INTERP_KERNEL::Exception(oss.str().c_str());
8935 arrIndexOut=arrIo.retn();
8939 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8940 * 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 ).
8941 * The selection of extraction is done standardly in new2old format.
8942 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8944 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8945 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8946 * \param [in] arrIn arr origin array from which the extraction will be done.
8947 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8948 * \param [out] arrOut the resulting array
8949 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8950 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8952 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8953 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8955 if(!arrIn || !arrIndxIn)
8956 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8957 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8958 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8959 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8960 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8961 const int *arrInPtr=arrIn->getConstPointer();
8962 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8963 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8966 int maxSizeOfArr=arrIn->getNumberOfTuples();
8967 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8969 arrIo->alloc((int)(sz+1),1);
8970 int idsIt=idsOfSelectStart;
8971 int *work=arrIo->getPointer();
8974 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8976 if(idsIt>=0 && idsIt<nbOfGrps)
8977 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8980 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8981 throw INTERP_KERNEL::Exception(oss.str().c_str());
8987 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8988 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8989 throw INTERP_KERNEL::Exception(oss.str().c_str());
8992 arro->alloc(lgth,1);
8993 work=arro->getPointer();
8994 idsIt=idsOfSelectStart;
8995 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8997 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8998 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9001 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9002 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9003 throw INTERP_KERNEL::Exception(oss.str().c_str());
9007 arrIndexOut=arrIo.retn();
9011 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9012 * 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
9013 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9014 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9016 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9017 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9018 * \param [in] arrIn arr origin array from which the extraction will be done.
9019 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9020 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9021 * \param [in] srcArrIndex index array of \b srcArr
9022 * \param [out] arrOut the resulting array
9023 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9025 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9027 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9028 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9029 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9031 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9032 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9033 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9034 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9035 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9036 std::vector<bool> v(nbOfTuples,true);
9038 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9039 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9040 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9042 if(*it>=0 && *it<nbOfTuples)
9045 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9049 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9050 throw INTERP_KERNEL::Exception(oss.str().c_str());
9053 srcArrIndexPtr=srcArrIndex->getConstPointer();
9054 arrIo->alloc(nbOfTuples+1,1);
9055 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9056 const int *arrInPtr=arrIn->getConstPointer();
9057 const int *srcArrPtr=srcArr->getConstPointer();
9058 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9059 int *arroPtr=arro->getPointer();
9060 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9064 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9065 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9069 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9070 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9071 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9075 arrIndexOut=arrIo.retn();
9079 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9080 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9082 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9083 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9084 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9085 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9086 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9087 * \param [in] srcArrIndex index array of \b srcArr
9089 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9091 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9092 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9094 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9095 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9096 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9097 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9098 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9099 int *arrInOutPtr=arrInOut->getPointer();
9100 const int *srcArrPtr=srcArr->getConstPointer();
9101 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9103 if(*it>=0 && *it<nbOfTuples)
9105 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9106 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9109 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] !";
9110 throw INTERP_KERNEL::Exception(oss.str().c_str());
9115 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9116 throw INTERP_KERNEL::Exception(oss.str().c_str());
9122 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9123 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9124 * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
9125 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9126 * A negative value in \b arrIn means that it is ignored.
9127 * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
9129 * \param [in] arrIn arr origin array from which the extraction will be done.
9130 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9131 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9132 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9134 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9136 int seed=0,nbOfDepthPeelingPerformed=0;
9137 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9141 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9142 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9143 * 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]].
9144 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9145 * A negative value in \b arrIn means that it is ignored.
9146 * 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.
9147 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9148 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9149 * \param [in] arrIn arr origin array from which the extraction will be done.
9150 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9151 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9152 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9153 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9154 * \sa MEDCouplingUMesh::partitionBySpreadZone
9156 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9158 nbOfDepthPeelingPerformed=0;
9160 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9161 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9164 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9168 std::vector<bool> fetched(nbOfTuples,false);
9169 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9172 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9174 nbOfDepthPeelingPerformed=0;
9175 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9176 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9177 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9178 std::vector<bool> fetched2(nbOfTuples,false);
9180 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9182 if(*seedElt>=0 && *seedElt<nbOfTuples)
9183 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9185 { 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()); }
9187 const int *arrInPtr=arrIn->getConstPointer();
9188 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9189 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9190 std::vector<int> idsToFetch1(seedBg,seedEnd);
9191 std::vector<int> idsToFetch2;
9192 std::vector<int> *idsToFetch=&idsToFetch1;
9193 std::vector<int> *idsToFetchOther=&idsToFetch2;
9194 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9196 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9197 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9199 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9200 std::swap(idsToFetch,idsToFetchOther);
9201 idsToFetchOther->clear();
9202 nbOfDepthPeelingPerformed++;
9204 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9207 int *retPtr=ret->getPointer();
9208 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9215 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9216 * 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
9217 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9218 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9220 * \param [in] start begin of set of ids of the input extraction (included)
9221 * \param [in] end end of set of ids of the input extraction (excluded)
9222 * \param [in] step step of the set of ids in range mode.
9223 * \param [in] arrIn arr origin array from which the extraction will be done.
9224 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9225 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9226 * \param [in] srcArrIndex index array of \b srcArr
9227 * \param [out] arrOut the resulting array
9228 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9230 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9232 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9233 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9234 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9236 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9237 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9240 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9242 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9243 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9244 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9246 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9248 if(it>=0 && it<nbOfTuples)
9249 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9252 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9253 throw INTERP_KERNEL::Exception(oss.str().c_str());
9256 srcArrIndexPtr=srcArrIndex->getConstPointer();
9257 arrIo->alloc(nbOfTuples+1,1);
9258 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9259 const int *arrInPtr=arrIn->getConstPointer();
9260 const int *srcArrPtr=srcArr->getConstPointer();
9261 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9262 int *arroPtr=arro->getPointer();
9263 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9265 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9268 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9269 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9273 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9274 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9278 arrIndexOut=arrIo.retn();
9282 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9283 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9285 * \param [in] start begin of set of ids of the input extraction (included)
9286 * \param [in] end end of set of ids of the input extraction (excluded)
9287 * \param [in] step step of the set of ids in range mode.
9288 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9289 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9290 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9291 * \param [in] srcArrIndex index array of \b srcArr
9293 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9295 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9296 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9298 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9299 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9300 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9301 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9302 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9303 int *arrInOutPtr=arrInOut->getPointer();
9304 const int *srcArrPtr=srcArr->getConstPointer();
9305 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9307 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9309 if(it>=0 && it<nbOfTuples)
9311 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9312 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9315 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9316 throw INTERP_KERNEL::Exception(oss.str().c_str());
9321 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9322 throw INTERP_KERNEL::Exception(oss.str().c_str());
9328 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9329 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9330 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9331 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9332 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9334 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9336 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9338 checkFullyDefined();
9339 int mdim=getMeshDimension();
9340 int spaceDim=getSpaceDimension();
9342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9343 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9344 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9345 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9347 ret->setCoords(getCoords());
9348 ret->allocateCells((int)partition.size());
9350 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9352 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9357 cell=tmp->buildUnionOf2DMesh();
9360 cell=tmp->buildUnionOf3DMesh();
9363 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9366 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9369 ret->finishInsertingCells();
9374 * This method partitions \b this into contiguous zone.
9375 * This method only needs a well defined connectivity. Coordinates are not considered here.
9376 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9378 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9380 int nbOfCellsCur=getNumberOfCells();
9381 std::vector<DataArrayInt *> ret;
9384 DataArrayInt *neigh=0,*neighI=0;
9385 computeNeighborsOfCells(neigh,neighI);
9386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9387 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9388 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9390 while(seed<nbOfCellsCur)
9392 int nbOfPeelPerformed=0;
9393 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9394 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9396 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9397 ret.push_back((*it).retn());
9402 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9403 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9405 * \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.
9406 * \return a newly allocated DataArrayInt to be managed by the caller.
9407 * \throw In case of \a code has not the right format (typically of size 3*n)
9409 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9411 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9412 std::size_t nb=code.size()/3;
9413 if(code.size()%3!=0)
9414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9415 ret->alloc((int)nb,2);
9416 int *retPtr=ret->getPointer();
9417 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9419 retPtr[0]=code[3*i+2];
9420 retPtr[1]=code[3*i+2]+code[3*i+1];
9426 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9427 * All cells in \a this are expected to be linear 3D cells.
9428 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9429 * It leads to an increase to number of cells.
9430 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9431 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9432 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9434 * \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.
9435 * For all other cells, the splitting policy will be ignored.
9436 * \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.
9437 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9438 * an id of old cell producing it. The caller is to delete this array using
9439 * decrRef() as it is no more needed.
9440 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9442 * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
9443 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9445 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9446 * \throw If \a this is not fully constituted with linear 3D cells.
9447 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9449 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9451 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9452 checkConnectivityFullyDefined();
9453 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9455 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9456 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9458 int *retPt(ret->getPointer());
9459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9460 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9461 const int *oldc(_nodal_connec->begin());
9462 const int *oldci(_nodal_connec_index->begin());
9463 const double *coords(_coords->begin());
9464 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9466 std::vector<int> a; std::vector<double> b;
9467 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9468 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9469 const int *aa(&a[0]);
9472 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9474 *it=(-(*(it))-1+nbNodes);
9475 addPts->insertAtTheEnd(b.begin(),b.end());
9476 nbNodes+=(int)b.size()/3;
9478 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9479 newConn->insertAtTheEnd(aa,aa+4);
9481 if(!addPts->empty())
9483 addPts->rearrange(3);
9484 nbOfAdditionalPoints=addPts->getNumberOfTuples();
9485 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9486 ret0->setCoords(addPts);
9490 nbOfAdditionalPoints=0;
9491 ret0->setCoords(getCoords());
9493 ret0->setNodalConnectivity(newConn);
9495 ret->computeOffsets2();
9496 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9500 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9501 _own_cell(true),_cell_id(-1),_nb_cell(0)
9506 _nb_cell=mesh->getNumberOfCells();
9510 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9518 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9519 _own_cell(false),_cell_id(bg-1),
9526 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9529 if(_cell_id<_nb_cell)
9538 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9544 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9546 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9549 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9555 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9563 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9569 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9574 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9579 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9581 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9584 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9589 _nb_cell=mesh->getNumberOfCells();
9593 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9600 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9602 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9603 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9604 if(_cell_id<_nb_cell)
9606 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9607 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9608 int startId=_cell_id;
9609 _cell_id+=nbOfElems;
9610 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9616 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9620 _conn=mesh->getNodalConnectivity()->getPointer();
9621 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9625 void MEDCouplingUMeshCell::next()
9627 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9632 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9635 std::string MEDCouplingUMeshCell::repr() const
9637 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9639 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9641 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9645 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9648 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9650 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9651 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9653 return INTERP_KERNEL::NORM_ERROR;
9656 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9659 if(_conn_lgth!=NOTICABLE_FIRST_VAL)