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.
422 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
424 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
430 * This method returns the sorted list of geometric types in \a this.
431 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
432 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
434 * \throw if connectivity in \a this is not correctly defined.
436 * \sa MEDCouplingMesh::getAllGeoTypes
438 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
440 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
441 checkConnectivityFullyDefined();
442 int nbOfCells(getNumberOfCells());
445 if(getMeshLength()<1)
446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
447 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
448 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
449 for(int i=1;i<nbOfCells;i++,ci++)
450 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
451 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
456 * This method is a method that compares \a this and \a other.
457 * This method compares \b all attributes, even names and component names.
459 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
463 std::ostringstream oss; oss.precision(15);
464 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
467 reason="mesh given in input is not castable in MEDCouplingUMesh !";
470 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
472 if(_mesh_dim!=otherC->_mesh_dim)
474 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
478 if(_types!=otherC->_types)
480 oss << "umesh geometric type mismatch :\nThis geometric types are :";
481 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
482 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
483 oss << "\nOther geometric types are :";
484 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
485 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
490 if(_nodal_connec==0 || otherC->_nodal_connec==0)
492 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
495 if(_nodal_connec!=otherC->_nodal_connec)
496 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
498 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
501 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
502 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
504 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
507 if(_nodal_connec_index!=otherC->_nodal_connec_index)
508 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
510 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
517 * Checks if data arrays of this mesh (node coordinates, nodal
518 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
520 * \param [in] other - the mesh to compare with.
521 * \param [in] prec - precision value used to compare node coordinates.
522 * \return bool - \a true if the two meshes are same.
524 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
526 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
529 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
531 if(_mesh_dim!=otherC->_mesh_dim)
533 if(_types!=otherC->_types)
535 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
536 if(_nodal_connec==0 || otherC->_nodal_connec==0)
538 if(_nodal_connec!=otherC->_nodal_connec)
539 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
541 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
542 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
544 if(_nodal_connec_index!=otherC->_nodal_connec_index)
545 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
551 * Checks if \a this and \a other meshes are geometrically equivalent with high
552 * probability, else an exception is thrown. The meshes are considered equivalent if
553 * (1) meshes contain the same number of nodes and the same number of elements of the
554 * same types (2) three cells of the two meshes (first, last and middle) are based
555 * on coincident nodes (with a specified precision).
556 * \param [in] other - the mesh to compare with.
557 * \param [in] prec - the precision used to compare nodes of the two meshes.
558 * \throw If the two meshes do not match.
560 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
562 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
563 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
565 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
569 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
570 * cells each node belongs to.
571 * \warning For speed reasons, this method does not check if node ids in the nodal
572 * connectivity correspond to the size of node coordinates array.
573 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
574 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
575 * dividing cell ids in \a revNodal into groups each referring to one
576 * node. Its every element (except the last one) is an index pointing to the
577 * first id of a group of cells. For example cells sharing the node #1 are
578 * described by following range of indices:
579 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
580 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
581 * Number of cells sharing the *i*-th node is
582 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
583 * \throw If the coordinates array is not set.
584 * \throw If the nodal connectivity of cells is not defined.
586 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
587 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
589 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
592 int nbOfNodes=getNumberOfNodes();
593 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
594 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
595 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
596 const int *conn=_nodal_connec->getConstPointer();
597 const int *connIndex=_nodal_connec_index->getConstPointer();
598 int nbOfCells=getNumberOfCells();
599 int nbOfEltsInRevNodal=0;
600 for(int eltId=0;eltId<nbOfCells;eltId++)
602 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
603 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
604 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
605 if(*iter>=0)//for polyhedrons
607 nbOfEltsInRevNodal++;
608 revNodalIndxPtr[(*iter)+1]++;
611 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
612 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
613 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
614 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
615 for(int eltId=0;eltId<nbOfCells;eltId++)
617 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620 if(*iter>=0)//for polyhedrons
621 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
627 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
632 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
638 if(cm.getOrientationStatus(nb,conn1,conn2))
645 class MinusOneSonsGenerator
648 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
649 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
650 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
651 static const int DELTA=1;
653 const INTERP_KERNEL::CellModel& _cm;
656 class MinusOneSonsGeneratorBiQuadratic
659 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
660 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
661 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
662 static const int DELTA=1;
664 const INTERP_KERNEL::CellModel& _cm;
667 class MinusTwoSonsGenerator
670 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
671 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
672 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
673 static const int DELTA=2;
675 const INTERP_KERNEL::CellModel& _cm;
681 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
682 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
683 * describing correspondence between cells of \a this and the result meshes are
684 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
685 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
686 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
687 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
688 * \warning For speed reasons, this method does not check if node ids in the nodal
689 * connectivity correspond to the size of node coordinates array.
690 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
691 * to write this mesh to the MED file, its cells must be sorted using
692 * sortCellsInMEDFileFrmt().
693 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
694 * each cell of \a this mesh.
695 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
696 * dividing cell ids in \a desc into groups each referring to one
697 * cell of \a this mesh. Its every element (except the last one) is an index
698 * pointing to the first id of a group of cells. For example cells of the
699 * result mesh bounding the cell #1 of \a this mesh are described by following
701 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
702 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
703 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
704 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
705 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
706 * by each cell of the result mesh.
707 * \param [in,out] revDescIndx - the array, of length one more than number of cells
708 * in the result mesh,
709 * dividing cell ids in \a revDesc into groups each referring to one
710 * cell of the result mesh the same way as \a descIndx divides \a desc.
711 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
712 * delete this mesh using decrRef() as it is no more needed.
713 * \throw If the coordinates array is not set.
714 * \throw If the nodal connectivity of cells is node defined.
715 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
716 * revDescIndx == NULL.
718 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
719 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
720 * \sa buildDescendingConnectivity2()
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
724 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
728 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732 * \sa MEDCouplingUMesh::buildDescendingConnectivity
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
737 if(getMeshDimension()!=3)
738 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
743 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744 * this->getMeshDimension(), that bound cells of \a this mesh. In
745 * addition arrays describing correspondence between cells of \a this and the result
746 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
747 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748 * mesh. This method differs from buildDescendingConnectivity() in that apart
749 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750 * result meshes. So a positive id means that order of nodes in corresponding cells
751 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753 * i.e. cell ids are one-based.
754 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
755 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
756 * \warning For speed reasons, this method does not check if node ids in the nodal
757 * connectivity correspond to the size of node coordinates array.
758 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759 * to write this mesh to the MED file, its cells must be sorted using
760 * sortCellsInMEDFileFrmt().
761 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
762 * each cell of \a this mesh.
763 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764 * dividing cell ids in \a desc into groups each referring to one
765 * cell of \a this mesh. Its every element (except the last one) is an index
766 * pointing to the first id of a group of cells. For example cells of the
767 * result mesh bounding the cell #1 of \a this mesh are described by following
769 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774 * by each cell of the result mesh.
775 * \param [in,out] revDescIndx - the array, of length one more than number of cells
776 * in the result mesh,
777 * dividing cell ids in \a revDesc into groups each referring to one
778 * cell of the result mesh the same way as \a descIndx divides \a desc.
779 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780 * shares the node coordinates array with \a this mesh. The caller is to
781 * delete this mesh using decrRef() as it is no more needed.
782 * \throw If the coordinates array is not set.
783 * \throw If the nodal connectivity of cells is node defined.
784 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785 * revDescIndx == NULL.
787 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
788 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
789 * \sa buildDescendingConnectivity()
791 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
793 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
797 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
798 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
799 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
800 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
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::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
812 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
814 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
818 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
819 * 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,
820 * excluding a set of meshdim-1 cells in input descending connectivity.
821 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
822 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
823 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
825 * \param [in] desc descending connectivity array.
826 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
827 * \param [in] revDesc reverse descending connectivity array.
828 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
829 * \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
830 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
831 * \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.
833 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
834 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
836 if(!desc || !descIndx || !revDesc || !revDescIndx)
837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
838 const int *descPtr=desc->getConstPointer();
839 const int *descIPtr=descIndx->getConstPointer();
840 const int *revDescPtr=revDesc->getConstPointer();
841 const int *revDescIPtr=revDescIndx->getConstPointer();
843 int nbCells=descIndx->getNumberOfTuples()-1;
844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
846 int *out1Ptr=out1->getPointer();
848 out0->reserve(desc->getNumberOfTuples());
849 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
851 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
853 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
855 out0->insertAtTheEnd(s.begin(),s.end());
857 *out1Ptr=out0->getNumberOfTuples();
859 neighbors=out0.retn();
860 neighborsIndx=out1.retn();
866 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
867 * For speed reasons no check of this will be done.
869 template<class SonsGenerator>
870 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
872 if(!desc || !descIndx || !revDesc || !revDescIndx)
873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
874 checkConnectivityFullyDefined();
875 int nbOfCells=getNumberOfCells();
876 int nbOfNodes=getNumberOfNodes();
877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
878 int *revNodalIndxPtr=revNodalIndx->getPointer();
879 const int *conn=_nodal_connec->getConstPointer();
880 const int *connIndex=_nodal_connec_index->getConstPointer();
881 std::string name="Mesh constituent of "; name+=getName();
882 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
883 ret->setCoords(getCoords());
884 ret->allocateCells(2*nbOfCells);
885 descIndx->alloc(nbOfCells+1,1);
886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
887 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
888 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
890 int pos=connIndex[eltId];
891 int posP1=connIndex[eltId+1];
892 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
893 SonsGenerator sg(cm);
894 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
895 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
896 for(unsigned i=0;i<nbOfSons;i++)
898 INTERP_KERNEL::NormalizedCellType cmsId;
899 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
900 for(unsigned k=0;k<nbOfNodesSon;k++)
902 revNodalIndxPtr[tmp[k]+1]++;
903 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
904 revDesc2->pushBackSilent(eltId);
906 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
908 int nbOfCellsM1=ret->getNumberOfCells();
909 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
911 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
912 int *revNodalPtr=revNodal->getPointer();
913 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
914 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
915 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
917 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
918 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
919 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
920 if(*iter>=0)//for polyhedrons
921 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
924 DataArrayInt *commonCells=0,*commonCellsI=0;
925 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
927 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
928 int newNbOfCellsM1=-1;
929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
930 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
931 std::vector<bool> isImpacted(nbOfCellsM1,false);
932 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
933 for(int work2=work[0];work2!=work[1];work2++)
934 isImpacted[commonCellsPtr[work2]]=true;
935 const int *o2nM1Ptr=o2nM1->getConstPointer();
936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
937 const int *n2oM1Ptr=n2oM1->getConstPointer();
938 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
939 ret2->copyTinyInfoFrom(this);
940 desc->alloc(descIndx->back(),1);
941 int *descPtr=desc->getPointer();
942 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
943 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
946 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
949 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
951 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
952 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
955 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
958 revDesc->reserve(newNbOfCellsM1);
959 revDescIndx->alloc(newNbOfCellsM1+1,1);
960 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
961 const int *revDesc2Ptr=revDesc2->getConstPointer();
962 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
964 int oldCellIdM1=n2oM1Ptr[i];
965 if(!isImpacted[oldCellIdM1])
967 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
968 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
972 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
973 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
974 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
982 struct MEDCouplingAccVisit
984 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
985 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
986 int _new_nb_of_nodes;
992 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
993 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
994 * array of cell ids. Pay attention that after conversion all algorithms work slower
995 * with \a this mesh than before conversion. <br> If an exception is thrown during the
996 * conversion due presence of invalid ids in the array of cells to convert, as a
997 * result \a this mesh contains some already converted elements. In this case the 2D
998 * mesh remains valid but 3D mesh becomes \b inconsistent!
999 * \warning This method can significantly modify the order of geometric types in \a this,
1000 * hence, to write this mesh to the MED file, its cells must be sorted using
1001 * sortCellsInMEDFileFrmt().
1002 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1003 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1004 * cellIdsToConvertBg.
1005 * \throw If the coordinates array is not set.
1006 * \throw If the nodal connectivity of cells is node defined.
1007 * \throw If dimension of \a this mesh is not either 2 or 3.
1009 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1010 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1012 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1014 checkFullyDefined();
1015 int dim=getMeshDimension();
1017 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1018 int nbOfCells=getNumberOfCells();
1021 const int *connIndex=_nodal_connec_index->getConstPointer();
1022 int *conn=_nodal_connec->getPointer();
1023 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1025 if(*iter>=0 && *iter<nbOfCells)
1027 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1028 if(!cm.isQuadratic())
1029 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1031 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1035 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1036 oss << " in range [0," << nbOfCells << ") !";
1037 throw INTERP_KERNEL::Exception(oss.str().c_str());
1043 int *connIndex=_nodal_connec_index->getPointer();
1044 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1045 const int *connOld=_nodal_connec->getConstPointer();
1046 int connOldLgth=_nodal_connec->getNbOfElems();
1047 std::vector<int> connNew(connOld,connOld+connOldLgth);
1048 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1050 if(*iter>=0 && *iter<nbOfCells)
1052 int pos=connIndex[*iter];
1053 int posP1=connIndex[(*iter)+1];
1054 int lgthOld=posP1-pos-1;
1055 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1056 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1057 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1058 int *tmp=new int[nbOfFaces*lgthOld];
1060 for(int j=0;j<(int)nbOfFaces;j++)
1062 INTERP_KERNEL::NormalizedCellType type;
1063 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1067 std::size_t newLgth=std::distance(tmp,work)-1;
1068 std::size_t delta=newLgth-lgthOld;
1069 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1070 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1071 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1076 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1077 oss << " in range [0," << nbOfCells << ") !";
1078 throw INTERP_KERNEL::Exception(oss.str().c_str());
1081 _nodal_connec->alloc((int)connNew.size(),1);
1082 int *newConnPtr=_nodal_connec->getPointer();
1083 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1089 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1090 * polyhedrons (if \a this is a 3D mesh).
1091 * \warning As this method is purely for user-friendliness and no optimization is
1092 * done to avoid construction of a useless vector, this method can be costly
1094 * \throw If the coordinates array is not set.
1095 * \throw If the nodal connectivity of cells is node defined.
1096 * \throw If dimension of \a this mesh is not either 2 or 3.
1098 void MEDCouplingUMesh::convertAllToPoly()
1100 int nbOfCells=getNumberOfCells();
1101 std::vector<int> cellIds(nbOfCells);
1102 for(int i=0;i<nbOfCells;i++)
1104 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1108 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1109 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1110 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1111 * base facet of the volume and the second half of nodes describes an opposite facet
1112 * having the same number of nodes as the base one. This method converts such
1113 * connectivity to a valid polyhedral format where connectivity of each facet is
1114 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1115 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1116 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1117 * a correct orientation of the first facet of a polyhedron, else orientation of a
1118 * corrected cell is reverse.<br>
1119 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1120 * it releases the user from boring description of polyhedra connectivity in the valid
1122 * \throw If \a this->getMeshDimension() != 3.
1123 * \throw If \a this->getSpaceDimension() != 3.
1124 * \throw If the nodal connectivity of cells is not defined.
1125 * \throw If the coordinates array is not set.
1126 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1127 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1129 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1130 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1132 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1134 checkFullyDefined();
1135 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1136 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1137 int nbOfCells=getNumberOfCells();
1138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1139 newCi->alloc(nbOfCells+1,1);
1140 int *newci=newCi->getPointer();
1141 const int *ci=_nodal_connec_index->getConstPointer();
1142 const int *c=_nodal_connec->getConstPointer();
1144 for(int i=0;i<nbOfCells;i++)
1146 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1147 if(type==INTERP_KERNEL::NORM_POLYHED)
1149 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1151 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1152 throw INTERP_KERNEL::Exception(oss.str().c_str());
1154 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1157 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 !";
1158 throw INTERP_KERNEL::Exception(oss.str().c_str());
1161 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)
1164 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1167 newC->alloc(newci[nbOfCells],1);
1168 int *newc=newC->getPointer();
1169 for(int i=0;i<nbOfCells;i++)
1171 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1172 if(type==INTERP_KERNEL::NORM_POLYHED)
1174 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1175 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1177 for(std::size_t j=0;j<n1;j++)
1179 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1181 newc[n1+5*j+1]=c[ci[i]+1+j];
1182 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1183 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1184 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1189 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1191 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1192 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1197 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1198 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1199 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1200 * to write this mesh to the MED file, its cells must be sorted using
1201 * sortCellsInMEDFileFrmt().
1202 * \return \c true if at least one cell has been converted, \c false else. In the
1203 * last case the nodal connectivity remains unchanged.
1204 * \throw If the coordinates array is not set.
1205 * \throw If the nodal connectivity of cells is not defined.
1206 * \throw If \a this->getMeshDimension() < 0.
1208 bool MEDCouplingUMesh::unPolyze()
1210 checkFullyDefined();
1211 int mdim=getMeshDimension();
1213 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1216 int nbOfCells=getNumberOfCells();
1219 int initMeshLgth=getMeshLength();
1220 int *conn=_nodal_connec->getPointer();
1221 int *index=_nodal_connec_index->getPointer();
1226 for(int i=0;i<nbOfCells;i++)
1228 lgthOfCurCell=index[i+1]-posOfCurCell;
1229 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1230 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1231 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1235 switch(cm.getDimension())
1239 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1240 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1241 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1246 int nbOfFaces,lgthOfPolyhConn;
1247 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1248 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1253 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1257 ret=ret || (newType!=type);
1258 conn[newPos]=newType;
1260 posOfCurCell=index[i+1];
1265 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1266 newPos+=lgthOfCurCell;
1267 posOfCurCell+=lgthOfCurCell;
1271 if(newPos!=initMeshLgth)
1272 _nodal_connec->reAlloc(newPos);
1279 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1280 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1281 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1283 * \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
1286 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1288 checkFullyDefined();
1289 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1290 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1291 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1292 coords->recenterForMaxPrecision(eps);
1294 int nbOfCells=getNumberOfCells();
1295 const int *conn=_nodal_connec->getConstPointer();
1296 const int *index=_nodal_connec_index->getConstPointer();
1297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1298 connINew->alloc(nbOfCells+1,1);
1299 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1302 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1304 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1306 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1310 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1311 *connINewPtr=connNew->getNumberOfTuples();
1314 setConnectivity(connNew,connINew,false);
1318 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1319 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1320 * the format of returned DataArrayInt instance.
1322 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1323 * \sa MEDCouplingUMesh::getNodeIdsInUse
1325 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1327 checkConnectivityFullyDefined();
1328 int nbOfCells=getNumberOfCells();
1329 const int *connIndex=_nodal_connec_index->getConstPointer();
1330 const int *conn=_nodal_connec->getConstPointer();
1331 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1332 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1333 std::vector<bool> retS(maxElt,false);
1334 for(int i=0;i<nbOfCells;i++)
1335 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1339 for(int i=0;i<maxElt;i++)
1342 DataArrayInt *ret=DataArrayInt::New();
1344 int *retPtr=ret->getPointer();
1345 for(int i=0;i<maxElt;i++)
1352 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1353 * \sa MEDCouplingUMesh::getNodeIdsInUse
1355 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1357 int nbOfNodes=(int)nodeIdsInUse.size();
1358 int nbOfCells=getNumberOfCells();
1359 const int *connIndex=_nodal_connec_index->getConstPointer();
1360 const int *conn=_nodal_connec->getConstPointer();
1361 for(int i=0;i<nbOfCells;i++)
1362 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1365 if(conn[j]<nbOfNodes)
1366 nodeIdsInUse[conn[j]]=true;
1369 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1370 throw INTERP_KERNEL::Exception(oss.str().c_str());
1376 * Finds nodes not used in any cell and returns an array giving a new id to every node
1377 * by excluding the unused nodes, for which the array holds -1. The result array is
1378 * a mapping in "Old to New" mode.
1379 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1380 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1381 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1382 * if the node is unused or a new id else. The caller is to delete this
1383 * array using decrRef() as it is no more needed.
1384 * \throw If the coordinates array is not set.
1385 * \throw If the nodal connectivity of cells is not defined.
1386 * \throw If the nodal connectivity includes an invalid id.
1388 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1389 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1390 * \sa computeNodeIdsAlg()
1392 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1395 int nbOfNodes=getNumberOfNodes();
1396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1397 ret->alloc(nbOfNodes,1);
1398 int *traducer=ret->getPointer();
1399 std::fill(traducer,traducer+nbOfNodes,-1);
1400 int nbOfCells=getNumberOfCells();
1401 const int *connIndex=_nodal_connec_index->getConstPointer();
1402 const int *conn=_nodal_connec->getConstPointer();
1403 for(int i=0;i<nbOfCells;i++)
1404 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1407 if(conn[j]<nbOfNodes)
1408 traducer[conn[j]]=1;
1411 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1412 throw INTERP_KERNEL::Exception(oss.str().c_str());
1415 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1416 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1421 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1422 * For each cell in \b this the number of nodes constituting cell is computed.
1423 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1424 * So for pohyhedrons some nodes can be counted several times in the returned result.
1426 * \return a newly allocated array
1427 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1429 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1431 checkConnectivityFullyDefined();
1432 int nbOfCells=getNumberOfCells();
1433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1434 ret->alloc(nbOfCells,1);
1435 int *retPtr=ret->getPointer();
1436 const int *conn=getNodalConnectivity()->getConstPointer();
1437 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1438 for(int i=0;i<nbOfCells;i++,retPtr++)
1440 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1441 *retPtr=connI[i+1]-connI[i]-1;
1443 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1449 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1450 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1452 * \return DataArrayInt * - new object to be deallocated by the caller.
1453 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1455 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1457 checkConnectivityFullyDefined();
1458 int nbOfCells=getNumberOfCells();
1459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1460 ret->alloc(nbOfCells,1);
1461 int *retPtr=ret->getPointer();
1462 const int *conn=getNodalConnectivity()->getConstPointer();
1463 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1464 for(int i=0;i<nbOfCells;i++,retPtr++)
1466 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1467 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1468 *retPtr=(int)s.size();
1472 *retPtr=(int)s.size();
1479 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1480 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1482 * \return a newly allocated array
1484 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1486 checkConnectivityFullyDefined();
1487 int nbOfCells=getNumberOfCells();
1488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1489 ret->alloc(nbOfCells,1);
1490 int *retPtr=ret->getPointer();
1491 const int *conn=getNodalConnectivity()->getConstPointer();
1492 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1493 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1495 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1496 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1502 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1503 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1504 * array mean that the corresponding old node is no more used.
1505 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1506 * this->getNumberOfNodes() before call of this method. The caller is to
1507 * delete this array using decrRef() as it is no more needed.
1508 * \throw If the coordinates array is not set.
1509 * \throw If the nodal connectivity of cells is not defined.
1510 * \throw If the nodal connectivity includes an invalid id.
1512 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1513 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1515 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1517 return MEDCouplingPointSet::zipCoordsTraducer();
1521 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1522 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1524 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1529 return AreCellsEqual0(conn,connI,cell1,cell2);
1531 return AreCellsEqual1(conn,connI,cell1,cell2);
1533 return AreCellsEqual2(conn,connI,cell1,cell2);
1535 return AreCellsEqual3(conn,connI,cell1,cell2);
1537 return AreCellsEqual7(conn,connI,cell1,cell2);
1539 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1543 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1545 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1547 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1548 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1553 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1555 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1557 int sz=connI[cell1+1]-connI[cell1];
1558 if(sz==connI[cell2+1]-connI[cell2])
1560 if(conn[connI[cell1]]==conn[connI[cell2]])
1562 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1563 unsigned dim=cm.getDimension();
1569 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1570 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1571 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1572 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1573 return work!=tmp+sz1?1:0;
1576 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1586 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1588 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1590 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1592 if(conn[connI[cell1]]==conn[connI[cell2]])
1594 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1595 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1603 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1605 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1607 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1609 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1610 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1617 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1619 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1621 int sz=connI[cell1+1]-connI[cell1];
1622 if(sz==connI[cell2+1]-connI[cell2])
1624 if(conn[connI[cell1]]==conn[connI[cell2]])
1626 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1627 unsigned dim=cm.getDimension();
1633 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1634 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1635 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1636 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1641 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1642 std::reverse_iterator<int *> it2((int *)tmp);
1643 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1649 return work!=tmp+sz1?1:0;
1652 {//case of SEG2 and SEG3
1653 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1655 if(!cm.isQuadratic())
1657 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1658 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1659 if(std::equal(it1,it2,conn+connI[cell2]+1))
1665 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])
1672 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1679 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1680 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1681 * and result remains unchanged.
1682 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1683 * If in 'candidates' pool -1 value is considered as an empty value.
1684 * WARNING this method returns only ONE set of result !
1686 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1688 if(candidates.size()<1)
1691 std::vector<int>::const_iterator iter=candidates.begin();
1692 int start=(*iter++);
1693 for(;iter!=candidates.end();iter++)
1695 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1700 result->pushBackSilent(start);
1704 result->pushBackSilent(*iter);
1706 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1713 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1714 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1716 * \param [in] compType input specifying the technique used to compare cells each other.
1717 * - 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.
1718 * - 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)
1719 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1720 * - 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
1721 * can be used for users not sensitive to orientation of cell
1722 * \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.
1723 * \param [out] commonCells
1724 * \param [out] commonCellsI
1725 * \return the correspondance array old to new in a newly allocated array.
1728 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1731 getReverseNodalConnectivity(revNodal,revNodalI);
1732 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1735 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1736 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1739 int nbOfCells=nodalI->getNumberOfTuples()-1;
1740 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1741 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1742 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1743 std::vector<bool> isFetched(nbOfCells,false);
1746 for(int i=0;i<nbOfCells;i++)
1750 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1751 std::vector<int> v,v2;
1752 if(connOfNode!=connPtr+connIPtr[i+1])
1754 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1755 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1758 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1762 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1763 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1764 v2.resize(std::distance(v2.begin(),it));
1768 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1770 int pos=commonCellsI->back();
1771 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1772 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1773 isFetched[*it]=true;
1781 for(int i=startCellId;i<nbOfCells;i++)
1785 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1786 std::vector<int> v,v2;
1787 if(connOfNode!=connPtr+connIPtr[i+1])
1789 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1792 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1796 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1797 v2.resize(std::distance(v2.begin(),it));
1801 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1803 int pos=commonCellsI->back();
1804 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1805 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1806 isFetched[*it]=true;
1812 commonCellsArr=commonCells.retn();
1813 commonCellsIArr=commonCellsI.retn();
1817 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1818 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1819 * than \a other->getNumberOfCells() in the returned array means that there is no
1820 * corresponding cell in \a this mesh.
1821 * It is expected that \a this and \a other meshes share the same node coordinates
1822 * array, if it is not so an exception is thrown.
1823 * \param [in] other - the mesh to compare with.
1824 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1825 * valid values [0,1,2], see zipConnectivityTraducer().
1826 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1827 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1828 * values. The caller is to delete this array using
1829 * decrRef() as it is no more needed.
1830 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1833 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1834 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1835 * \sa checkDeepEquivalOnSameNodesWith()
1836 * \sa checkGeoEquivalWith()
1838 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1840 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1841 int nbOfCells=getNumberOfCells();
1842 static const int possibleCompType[]={0,1,2};
1843 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1845 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1846 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1848 throw INTERP_KERNEL::Exception(oss.str().c_str());
1850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1851 arr=o2n->substr(nbOfCells);
1852 arr->setName(other->getName().c_str());
1854 if(other->getNumberOfCells()==0)
1856 return arr->getMaxValue(tmp)<nbOfCells;
1860 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1861 * This method tries to determine if \b other is fully included in \b this.
1862 * The main difference is that this method is not expected to throw exception.
1863 * This method has two outputs :
1865 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1866 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1868 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1870 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1871 DataArrayInt *commonCells=0,*commonCellsI=0;
1872 int thisNbCells=getNumberOfCells();
1873 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1874 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1875 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1876 int otherNbCells=other->getNumberOfCells();
1877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1878 arr2->alloc(otherNbCells,1);
1879 arr2->fillWithZero();
1880 int *arr2Ptr=arr2->getPointer();
1881 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1882 for(int i=0;i<nbOfCommon;i++)
1884 int start=commonCellsPtr[commonCellsIPtr[i]];
1885 if(start<thisNbCells)
1887 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1889 int sig=commonCellsPtr[j]>0?1:-1;
1890 int val=std::abs(commonCellsPtr[j])-1;
1891 if(val>=thisNbCells)
1892 arr2Ptr[val-thisNbCells]=sig*(start+1);
1896 arr2->setName(other->getName().c_str());
1897 if(arr2->presenceOfValue(0))
1903 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1906 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1907 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1910 std::vector<const MEDCouplingUMesh *> ms(2);
1913 return MergeUMeshesOnSameCoords(ms);
1917 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1918 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1919 * cellIds is not given explicitely but by a range python like.
1921 * \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.
1922 * \return a newly allocated
1924 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1925 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1927 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1929 if(getMeshDimension()!=-1)
1930 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1933 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1935 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1937 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1939 return const_cast<MEDCouplingUMesh *>(this);
1944 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1945 * The result mesh shares or not the node coordinates array with \a this mesh depending
1946 * on \a keepCoords parameter.
1947 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1948 * to write this mesh to the MED file, its cells must be sorted using
1949 * sortCellsInMEDFileFrmt().
1950 * \param [in] begin - an array of cell ids to include to the new mesh.
1951 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1952 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1953 * array of \a this mesh, else "free" nodes are removed from the result mesh
1954 * by calling zipCoords().
1955 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1956 * to delete this mesh using decrRef() as it is no more needed.
1957 * \throw If the coordinates array is not set.
1958 * \throw If the nodal connectivity of cells is not defined.
1959 * \throw If any cell id in the array \a begin is not valid.
1961 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1962 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1964 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1966 if(getMeshDimension()!=-1)
1967 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1971 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1973 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1975 return const_cast<MEDCouplingUMesh *>(this);
1980 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1982 * 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.
1983 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1984 * The number of cells of \b this will remain the same with this method.
1986 * \param [in] begin begin of cell ids (included) of cells in this to assign
1987 * \param [in] end end of cell ids (excluded) of cells in this to assign
1988 * \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 ).
1989 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1991 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1993 checkConnectivityFullyDefined();
1994 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1995 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1996 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1997 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1999 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2000 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2001 throw INTERP_KERNEL::Exception(oss.str().c_str());
2003 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2004 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2006 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2007 throw INTERP_KERNEL::Exception(oss.str().c_str());
2009 int nbOfCells=getNumberOfCells();
2010 bool easyAssign=true;
2011 const int *connI=_nodal_connec_index->getConstPointer();
2012 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2013 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2015 if(*it>=0 && *it<nbOfCells)
2017 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2021 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2022 throw INTERP_KERNEL::Exception(oss.str().c_str());
2027 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2032 DataArrayInt *arrOut=0,*arrIOut=0;
2033 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2036 setConnectivity(arrOut,arrIOut,true);
2040 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2042 checkConnectivityFullyDefined();
2043 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2044 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2045 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2046 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2048 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2049 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2050 throw INTERP_KERNEL::Exception(oss.str().c_str());
2052 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2053 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2055 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2056 throw INTERP_KERNEL::Exception(oss.str().c_str());
2058 int nbOfCells=getNumberOfCells();
2059 bool easyAssign=true;
2060 const int *connI=_nodal_connec_index->getConstPointer();
2061 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2063 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2065 if(it>=0 && it<nbOfCells)
2067 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2071 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2072 throw INTERP_KERNEL::Exception(oss.str().c_str());
2077 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2082 DataArrayInt *arrOut=0,*arrIOut=0;
2083 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2086 setConnectivity(arrOut,arrIOut,true);
2091 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2092 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2093 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2094 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2096 * \param [in] begin input start of array of node ids.
2097 * \param [in] end input end of array of node ids.
2098 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2099 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2101 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2104 checkConnectivityFullyDefined();
2106 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2107 std::vector<bool> fastFinder(sz,false);
2108 for(const int *work=begin;work!=end;work++)
2109 if(*work>=0 && *work<sz)
2110 fastFinder[*work]=true;
2111 int nbOfCells=getNumberOfCells();
2112 const int *conn=getNodalConnectivity()->getConstPointer();
2113 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2114 for(int i=0;i<nbOfCells;i++)
2116 int ref=0,nbOfHit=0;
2117 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2121 if(fastFinder[*work2])
2124 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2125 cellIdsKept->pushBackSilent(i);
2127 cellIdsKeptArr=cellIdsKept.retn();
2131 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2132 * this->getMeshDimension(), that bound some cells of \a this mesh.
2133 * The cells of lower dimension to include to the result mesh are selected basing on
2134 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2135 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2136 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2137 * created mesh shares the node coordinates array with \a this mesh.
2138 * \param [in] begin - the array of node ids.
2139 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2140 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2141 * array \a begin are added, else cells whose any node is in the
2142 * array \a begin are added.
2143 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2144 * to delete this mesh using decrRef() as it is no more needed.
2145 * \throw If the coordinates array is not set.
2146 * \throw If the nodal connectivity of cells is not defined.
2147 * \throw If any node id in \a begin is not valid.
2149 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2150 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2152 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2154 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2155 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2156 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2157 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2158 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2162 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2163 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2164 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2165 * array of \a this mesh, else "free" nodes are removed from the result mesh
2166 * by calling zipCoords().
2167 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2168 * to delete this mesh using decrRef() as it is no more needed.
2169 * \throw If the coordinates array is not set.
2170 * \throw If the nodal connectivity of cells is not defined.
2172 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2173 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2175 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2177 DataArrayInt *desc=DataArrayInt::New();
2178 DataArrayInt *descIndx=DataArrayInt::New();
2179 DataArrayInt *revDesc=DataArrayInt::New();
2180 DataArrayInt *revDescIndx=DataArrayInt::New();
2182 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2185 descIndx->decrRef();
2186 int nbOfCells=meshDM1->getNumberOfCells();
2187 const int *revDescIndxC=revDescIndx->getConstPointer();
2188 std::vector<int> boundaryCells;
2189 for(int i=0;i<nbOfCells;i++)
2190 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2191 boundaryCells.push_back(i);
2192 revDescIndx->decrRef();
2193 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2198 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2199 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2200 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2202 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2204 checkFullyDefined();
2205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2210 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2211 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2215 const int *revDescPtr=revDesc->getConstPointer();
2216 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2217 int nbOfCells=getNumberOfCells();
2218 std::vector<bool> ret1(nbOfCells,false);
2220 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2221 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2222 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2224 DataArrayInt *ret2=DataArrayInt::New();
2226 int *ret2Ptr=ret2->getPointer();
2228 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2231 ret2->setName("BoundaryCells");
2236 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2237 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2238 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2239 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2241 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2242 * This method method returns cells ids set s = s1 + s2 where :
2244 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2245 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2247 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2248 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2250 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2251 * \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
2252 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2254 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2256 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2257 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2258 checkConnectivityFullyDefined();
2259 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2260 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2261 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2264 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2266 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2267 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2268 DataArrayInt *idsOtherInConsti=0;
2269 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2272 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2274 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2275 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2278 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2279 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2281 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2282 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2283 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2284 neighThisPartAuto=0;
2285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2286 const int li[2]={0,1};
2287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2288 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2292 cellIdsRk0=s0arr.retn();
2293 cellIdsRk1=s_renum1.retn();
2297 * 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
2298 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2300 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2302 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2304 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2309 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2310 revDesc=0; desc=0; descIndx=0;
2311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2313 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2317 * Finds nodes lying on the boundary of \a this mesh.
2318 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2319 * nodes. The caller is to delete this array using decrRef() as it is no
2321 * \throw If the coordinates array is not set.
2322 * \throw If the nodal connectivity of cells is node defined.
2324 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2325 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2327 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2329 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2330 return skin->computeFetchedNodeIds();
2333 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2336 return const_cast<MEDCouplingUMesh *>(this);
2340 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2341 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2342 * 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.
2343 * 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.
2344 * 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.
2346 * \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
2347 * parameter is altered during the call.
2348 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2349 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2350 * \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.
2352 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2354 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2355 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2357 checkFullyDefined();
2358 otherDimM1OnSameCoords.checkFullyDefined();
2359 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2360 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2361 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2363 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2364 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2367 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2368 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2372 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2374 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2376 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2377 DataArrayInt *idsTmp=0;
2378 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2382 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2383 DataArrayInt *tmp0=0,*tmp1=0;
2384 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2389 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2390 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2392 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2393 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2394 nodeIdsToDuplicate=s3.retn();
2398 * This method operates a modification of the connectivity and coords in \b this.
2399 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2400 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2401 * 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
2402 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2403 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2405 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2407 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2408 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2410 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2412 int nbOfNodes=getNumberOfNodes();
2413 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2414 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2418 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2419 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2420 * This method is a generalization of shiftNodeNumbersInConn().
2421 * \warning This method performs no check of validity of new ids. **Use it with care !**
2422 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2423 * this->getNumberOfNodes(), in "Old to New" mode.
2424 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2425 * \throw If the nodal connectivity of cells is not defined.
2427 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2428 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2430 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2432 checkConnectivityFullyDefined();
2433 int *conn=getNodalConnectivity()->getPointer();
2434 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2435 int nbOfCells=getNumberOfCells();
2436 for(int i=0;i<nbOfCells;i++)
2437 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2439 int& node=conn[iconn];
2440 if(node>=0)//avoid polyhedron separator
2442 node=newNodeNumbersO2N[node];
2445 _nodal_connec->declareAsNew();
2450 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2451 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2452 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2454 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2456 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2458 checkConnectivityFullyDefined();
2459 int *conn=getNodalConnectivity()->getPointer();
2460 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2461 int nbOfCells=getNumberOfCells();
2462 for(int i=0;i<nbOfCells;i++)
2463 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2465 int& node=conn[iconn];
2466 if(node>=0)//avoid polyhedron separator
2471 _nodal_connec->declareAsNew();
2476 * This method operates a modification of the connectivity in \b this.
2477 * 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.
2478 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2479 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2480 * 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
2481 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2482 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2484 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2485 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2487 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2488 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2489 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2491 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2493 checkConnectivityFullyDefined();
2494 std::map<int,int> m;
2496 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2498 int *conn=getNodalConnectivity()->getPointer();
2499 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2500 int nbOfCells=getNumberOfCells();
2501 for(int i=0;i<nbOfCells;i++)
2502 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2504 int& node=conn[iconn];
2505 if(node>=0)//avoid polyhedron separator
2507 std::map<int,int>::iterator it=m.find(node);
2516 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2518 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2519 * After the call of this method the number of cells remains the same as before.
2521 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2522 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2523 * be strictly in [0;this->getNumberOfCells()).
2525 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2526 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2527 * should be contained in[0;this->getNumberOfCells()).
2529 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2531 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2533 checkConnectivityFullyDefined();
2534 int nbCells=getNumberOfCells();
2535 const int *array=old2NewBg;
2537 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2539 const int *conn=_nodal_connec->getConstPointer();
2540 const int *connI=_nodal_connec_index->getConstPointer();
2541 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2542 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2543 const int *n2oPtr=n2o->begin();
2544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2545 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2546 newConn->copyStringInfoFrom(*_nodal_connec);
2547 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2548 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2549 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2551 int *newC=newConn->getPointer();
2552 int *newCI=newConnI->getPointer();
2555 for(int i=0;i<nbCells;i++)
2558 int nbOfElts=connI[pos+1]-connI[pos];
2559 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2564 setConnectivity(newConn,newConnI);
2566 free(const_cast<int *>(array));
2570 * Finds cells whose bounding boxes intersect a given bounding box.
2571 * \param [in] bbox - an array defining the bounding box via coordinates of its
2572 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2574 * \param [in] eps - a factor used to increase size of the bounding box of cell
2575 * before comparing it with \a bbox. This factor is multiplied by the maximal
2576 * extent of the bounding box of cell to produce an addition to this bounding box.
2577 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2578 * cells. The caller is to delete this array using decrRef() as it is no more
2580 * \throw If the coordinates array is not set.
2581 * \throw If the nodal connectivity of cells is not defined.
2583 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2584 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2586 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2589 if(getMeshDimension()==-1)
2591 elems->pushBackSilent(0);
2592 return elems.retn();
2594 int dim=getSpaceDimension();
2595 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2596 const int* conn = getNodalConnectivity()->getConstPointer();
2597 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2598 const double* coords = getCoords()->getConstPointer();
2599 int nbOfCells=getNumberOfCells();
2600 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2602 for (int i=0; i<dim; i++)
2604 elem_bb[i*2]=std::numeric_limits<double>::max();
2605 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2608 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2610 int node= conn[inode];
2611 if(node>=0)//avoid polyhedron separator
2613 for (int idim=0; idim<dim; idim++)
2615 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2617 elem_bb[idim*2] = coords[node*dim+idim] ;
2619 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2621 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2626 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2627 elems->pushBackSilent(ielem);
2629 return elems.retn();
2633 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2634 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2635 * added in 'elems' parameter.
2637 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2640 if(getMeshDimension()==-1)
2642 elems->pushBackSilent(0);
2643 return elems.retn();
2645 int dim=getSpaceDimension();
2646 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2647 const int* conn = getNodalConnectivity()->getConstPointer();
2648 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2649 const double* coords = getCoords()->getConstPointer();
2650 int nbOfCells=getNumberOfCells();
2651 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2653 for (int i=0; i<dim; i++)
2655 elem_bb[i*2]=std::numeric_limits<double>::max();
2656 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2659 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2661 int node= conn[inode];
2662 if(node>=0)//avoid polyhedron separator
2664 for (int idim=0; idim<dim; idim++)
2666 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2668 elem_bb[idim*2] = coords[node*dim+idim] ;
2670 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2672 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2677 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2678 elems->pushBackSilent(ielem);
2680 return elems.retn();
2684 * Returns a type of a cell by its id.
2685 * \param [in] cellId - the id of the cell of interest.
2686 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2687 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2689 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2691 const int *ptI=_nodal_connec_index->getConstPointer();
2692 const int *pt=_nodal_connec->getConstPointer();
2693 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2694 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2697 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2698 throw INTERP_KERNEL::Exception(oss.str().c_str());
2703 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2704 * This method does not throw exception if geometric type \a type is not in \a this.
2705 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2706 * The coordinates array is not considered here.
2708 * \param [in] type the geometric type
2709 * \return cell ids in this having geometric type \a type.
2711 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2716 checkConnectivityFullyDefined();
2717 int nbCells=getNumberOfCells();
2718 int mdim=getMeshDimension();
2719 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2720 if(mdim!=(int)cm.getDimension())
2721 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2722 const int *ptI=_nodal_connec_index->getConstPointer();
2723 const int *pt=_nodal_connec->getConstPointer();
2724 for(int i=0;i<nbCells;i++)
2726 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2727 ret->pushBackSilent(i);
2733 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2735 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2737 const int *ptI=_nodal_connec_index->getConstPointer();
2738 const int *pt=_nodal_connec->getConstPointer();
2739 int nbOfCells=getNumberOfCells();
2741 for(int i=0;i<nbOfCells;i++)
2742 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2748 * Returns the nodal connectivity of a given cell.
2749 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2750 * all returned node ids can be used in getCoordinatesOfNode().
2751 * \param [in] cellId - an id of the cell of interest.
2752 * \param [in,out] conn - a vector where the node ids are appended. It is not
2753 * cleared before the appending.
2754 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2756 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2758 const int *ptI=_nodal_connec_index->getConstPointer();
2759 const int *pt=_nodal_connec->getConstPointer();
2760 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2765 std::string MEDCouplingUMesh::simpleRepr() const
2767 static const char msg0[]="No coordinates specified !";
2768 std::ostringstream ret;
2769 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2770 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2772 double tt=getTime(tmpp1,tmpp2);
2773 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2774 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2776 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2778 { ret << " Mesh dimension has not been set or is invalid !"; }
2781 const int spaceDim=getSpaceDimension();
2782 ret << spaceDim << "\nInfo attached on space dimension : ";
2783 for(int i=0;i<spaceDim;i++)
2784 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2788 ret << msg0 << "\n";
2789 ret << "Number of nodes : ";
2791 ret << getNumberOfNodes() << "\n";
2793 ret << msg0 << "\n";
2794 ret << "Number of cells : ";
2795 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2796 ret << getNumberOfCells() << "\n";
2798 ret << "No connectivity specified !" << "\n";
2799 ret << "Cell types present : ";
2800 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2802 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2803 ret << cm.getRepr() << " ";
2809 std::string MEDCouplingUMesh::advancedRepr() const
2811 std::ostringstream ret;
2812 ret << simpleRepr();
2813 ret << "\nCoordinates array : \n___________________\n\n";
2815 _coords->reprWithoutNameStream(ret);
2817 ret << "No array set !\n";
2818 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2819 reprConnectivityOfThisLL(ret);
2824 * This method returns a C++ code that is a dump of \a this.
2825 * This method will throw if this is not fully defined.
2827 std::string MEDCouplingUMesh::cppRepr() const
2829 static const char coordsName[]="coords";
2830 static const char connName[]="conn";
2831 static const char connIName[]="connI";
2832 checkFullyDefined();
2833 std::ostringstream ret; ret << "// coordinates" << std::endl;
2834 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2835 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2836 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2837 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2838 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2839 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2840 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2844 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2846 std::ostringstream ret;
2847 reprConnectivityOfThisLL(ret);
2852 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2853 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2854 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2857 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2858 * 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
2859 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2861 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2863 int mdim=getMeshDimension();
2865 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2866 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2867 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2868 bool needToCpyCT=true;
2871 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2879 if(!_nodal_connec_index)
2881 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2886 tmp2=_nodal_connec_index;
2889 ret->setConnectivity(tmp1,tmp2,false);
2894 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2895 ret->setCoords(coords);
2898 ret->setCoords(_coords);
2902 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2904 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2906 int nbOfCells=getNumberOfCells();
2907 const int *c=_nodal_connec->getConstPointer();
2908 const int *ci=_nodal_connec_index->getConstPointer();
2909 for(int i=0;i<nbOfCells;i++)
2911 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2912 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2913 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2918 stream << "Connectivity not defined !\n";
2921 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2923 const int *ptI=_nodal_connec_index->getConstPointer();
2924 const int *pt=_nodal_connec->getConstPointer();
2925 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2926 return ptI[cellId+1]-ptI[cellId]-1;
2928 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2932 * Returns types of cells of the specified part of \a this mesh.
2933 * This method avoids computing sub-mesh explicitely to get its types.
2934 * \param [in] begin - an array of cell ids of interest.
2935 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2936 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2937 * describing the cell types.
2938 * \throw If the coordinates array is not set.
2939 * \throw If the nodal connectivity of cells is not defined.
2940 * \sa getAllGeoTypes()
2942 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2944 checkFullyDefined();
2945 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2946 const int *conn=_nodal_connec->getConstPointer();
2947 const int *connIndex=_nodal_connec_index->getConstPointer();
2948 for(const int *w=begin;w!=end;w++)
2949 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2954 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2955 * a set of types of cells constituting \a this mesh.
2956 * This method is for advanced users having prepared their connectivity before. For
2957 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2958 * \param [in] conn - the nodal connectivity array.
2959 * \param [in] connIndex - the nodal connectivity index array.
2960 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2963 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2965 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2966 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2967 if(isComputingTypes)
2973 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2974 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2976 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2977 _nodal_connec(0),_nodal_connec_index(0),
2978 _types(other._types)
2980 if(other._nodal_connec)
2981 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2982 if(other._nodal_connec_index)
2983 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2986 MEDCouplingUMesh::~MEDCouplingUMesh()
2989 _nodal_connec->decrRef();
2990 if(_nodal_connec_index)
2991 _nodal_connec_index->decrRef();
2995 * Recomputes a set of cell types of \a this mesh. For more info see
2996 * \ref MEDCouplingUMeshNodalConnectivity.
2998 void MEDCouplingUMesh::computeTypes()
3000 if(_nodal_connec && _nodal_connec_index)
3003 const int *conn=_nodal_connec->getConstPointer();
3004 const int *connIndex=_nodal_connec_index->getConstPointer();
3005 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3007 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3008 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3013 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3015 void MEDCouplingUMesh::checkFullyDefined() const
3017 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3018 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3022 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3024 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3026 if(!_nodal_connec_index || !_nodal_connec)
3027 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3031 * Returns a number of cells constituting \a this mesh.
3032 * \return int - the number of cells in \a this mesh.
3033 * \throw If the nodal connectivity of cells is not defined.
3035 int MEDCouplingUMesh::getNumberOfCells() const
3037 if(_nodal_connec_index)
3038 return _nodal_connec_index->getNumberOfTuples()-1;
3043 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3047 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3048 * mesh. For more info see \ref MEDCouplingMeshesPage.
3049 * \return int - the dimension of \a this mesh.
3050 * \throw If the mesh dimension is not defined using setMeshDimension().
3052 int MEDCouplingUMesh::getMeshDimension() const
3055 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3060 * Returns a length of the nodal connectivity array.
3061 * This method is for test reason. Normally the integer returned is not useable by
3062 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3063 * \return int - the length of the nodal connectivity array.
3065 int MEDCouplingUMesh::getMeshLength() const
3067 return _nodal_connec->getNbOfElems();
3071 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3073 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3075 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3076 tinyInfo.push_back(getMeshDimension());
3077 tinyInfo.push_back(getNumberOfCells());
3079 tinyInfo.push_back(getMeshLength());
3081 tinyInfo.push_back(-1);
3085 * First step of unserialization process.
3087 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3089 return tinyInfo[6]<=0;
3093 * Second step of serialization process.
3094 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3096 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3098 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3100 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3104 * Third and final step of serialization process.
3106 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3108 MEDCouplingPointSet::serialize(a1,a2);
3109 if(getMeshDimension()>-1)
3111 a1=DataArrayInt::New();
3112 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3113 int *ptA1=a1->getPointer();
3114 const int *conn=getNodalConnectivity()->getConstPointer();
3115 const int *index=getNodalConnectivityIndex()->getConstPointer();
3116 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3117 std::copy(conn,conn+getMeshLength(),ptA1);
3124 * Second and final unserialization process.
3125 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3127 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3129 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3130 setMeshDimension(tinyInfo[5]);
3134 const int *recvBuffer=a1->getConstPointer();
3135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3136 myConnecIndex->alloc(tinyInfo[6]+1,1);
3137 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3139 myConnec->alloc(tinyInfo[7],1);
3140 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3141 setConnectivity(myConnec, myConnecIndex);
3146 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3147 * CellIds are given using range specified by a start an end and step.
3149 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3151 checkFullyDefined();
3152 int ncell=getNumberOfCells();
3153 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3154 ret->_mesh_dim=_mesh_dim;
3155 ret->setCoords(_coords);
3156 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3157 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3158 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3160 const int *conn=_nodal_connec->getConstPointer();
3161 const int *connIndex=_nodal_connec_index->getConstPointer();
3162 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3164 if(work>=0 && work<ncell)
3166 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3170 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3171 throw INTERP_KERNEL::Exception(oss.str().c_str());
3174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3175 int *newConnPtr=newConn->getPointer();
3176 std::set<INTERP_KERNEL::NormalizedCellType> types;
3178 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3180 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3181 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3183 ret->setConnectivity(newConn,newConnI,false);
3185 ret->copyTinyInfoFrom(this);
3190 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3191 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3192 * The return newly allocated mesh will share the same coordinates as \a this.
3194 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3196 checkConnectivityFullyDefined();
3197 int ncell=getNumberOfCells();
3198 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3199 ret->_mesh_dim=_mesh_dim;
3200 ret->setCoords(_coords);
3201 std::size_t nbOfElemsRet=std::distance(begin,end);
3202 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3204 const int *conn=_nodal_connec->getConstPointer();
3205 const int *connIndex=_nodal_connec_index->getConstPointer();
3207 for(const int *work=begin;work!=end;work++,newNbring++)
3209 if(*work>=0 && *work<ncell)
3210 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3214 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3215 throw INTERP_KERNEL::Exception(oss.str().c_str());
3218 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3219 int *connRetWork=connRet;
3220 std::set<INTERP_KERNEL::NormalizedCellType> types;
3221 for(const int *work=begin;work!=end;work++)
3223 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3224 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3227 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3228 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3229 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3230 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3232 ret->copyTinyInfoFrom(this);
3237 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3239 * For 1D cells, the returned field contains lengths.<br>
3240 * For 2D cells, the returned field contains areas.<br>
3241 * For 3D cells, the returned field contains volumes.
3242 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3243 * orientation, i.e. the volume is always positive.
3244 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3245 * and one time . The caller is to delete this field using decrRef() as it is no
3248 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3250 std::string name="MeasureOfMesh_";
3252 int nbelem=getNumberOfCells();
3253 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3254 field->setName(name.c_str());
3255 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3256 array->alloc(nbelem,1);
3257 double *area_vol=array->getPointer();
3258 field->setArray(array) ; array=0;
3259 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3260 field->synchronizeTimeWithMesh();
3261 if(getMeshDimension()!=-1)
3264 INTERP_KERNEL::NormalizedCellType type;
3265 int dim_space=getSpaceDimension();
3266 const double *coords=getCoords()->getConstPointer();
3267 const int *connec=getNodalConnectivity()->getConstPointer();
3268 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3269 for(int iel=0;iel<nbelem;iel++)
3271 ipt=connec_index[iel];
3272 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3273 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);
3276 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3280 area_vol[0]=std::numeric_limits<double>::max();
3282 return field.retn();
3286 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3288 * For 1D cells, the returned array contains lengths.<br>
3289 * For 2D cells, the returned array contains areas.<br>
3290 * For 3D cells, the returned array contains volumes.
3291 * This method avoids building explicitly a part of \a this mesh to perform the work.
3292 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3293 * orientation, i.e. the volume is always positive.
3294 * \param [in] begin - an array of cell ids of interest.
3295 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3296 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3297 * delete this array using decrRef() as it is no more needed.
3299 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3300 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3301 * \sa getMeasureField()
3303 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3305 std::string name="PartMeasureOfMesh_";
3307 int nbelem=(int)std::distance(begin,end);
3308 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3309 array->setName(name.c_str());
3310 array->alloc(nbelem,1);
3311 double *area_vol=array->getPointer();
3312 if(getMeshDimension()!=-1)
3315 INTERP_KERNEL::NormalizedCellType type;
3316 int dim_space=getSpaceDimension();
3317 const double *coords=getCoords()->getConstPointer();
3318 const int *connec=getNodalConnectivity()->getConstPointer();
3319 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3320 for(const int *iel=begin;iel!=end;iel++)
3322 ipt=connec_index[*iel];
3323 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3324 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3327 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3331 area_vol[0]=std::numeric_limits<double>::max();
3333 return array.retn();
3337 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3338 * \a this one. The returned field contains the dual cell volume for each corresponding
3339 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3340 * the dual mesh in P1 sens of \a this.<br>
3341 * For 1D cells, the returned field contains lengths.<br>
3342 * For 2D cells, the returned field contains areas.<br>
3343 * For 3D cells, the returned field contains volumes.
3344 * This method is useful to check "P1*" conservative interpolators.
3345 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3346 * orientation, i.e. the volume is always positive.
3347 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3348 * nodes and one time. The caller is to delete this array using decrRef() as
3349 * it is no more needed.
3351 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3353 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3354 std::string name="MeasureOnNodeOfMesh_";
3356 int nbNodes=getNumberOfNodes();
3357 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3358 double cst=1./((double)getMeshDimension()+1.);
3359 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3360 array->alloc(nbNodes,1);
3361 double *valsToFill=array->getPointer();
3362 std::fill(valsToFill,valsToFill+nbNodes,0.);
3363 const double *values=tmp->getArray()->getConstPointer();
3364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3366 getReverseNodalConnectivity(da,daInd);
3367 const int *daPtr=da->getConstPointer();
3368 const int *daIPtr=daInd->getConstPointer();
3369 for(int i=0;i<nbNodes;i++)
3370 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3371 valsToFill[i]+=cst*values[*cell];
3373 ret->setArray(array);
3378 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3379 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3380 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3381 * and are normalized.
3382 * <br> \a this can be either
3383 * - a 2D mesh in 2D or 3D space or
3384 * - an 1D mesh in 2D space.
3386 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3387 * cells and one time. The caller is to delete this field using decrRef() as
3388 * it is no more needed.
3389 * \throw If the nodal connectivity of cells is not defined.
3390 * \throw If the coordinates array is not set.
3391 * \throw If the mesh dimension is not set.
3392 * \throw If the mesh and space dimension is not as specified above.
3394 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3396 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3397 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3398 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3399 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3400 int nbOfCells=getNumberOfCells();
3401 int nbComp=getMeshDimension()+1;
3402 array->alloc(nbOfCells,nbComp);
3403 double *vals=array->getPointer();
3404 const int *connI=_nodal_connec_index->getConstPointer();
3405 const int *conn=_nodal_connec->getConstPointer();
3406 const double *coords=_coords->getConstPointer();
3407 if(getMeshDimension()==2)
3409 if(getSpaceDimension()==3)
3411 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3412 const double *locPtr=loc->getConstPointer();
3413 for(int i=0;i<nbOfCells;i++,vals+=3)
3415 int offset=connI[i];
3416 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3417 double n=INTERP_KERNEL::norm<3>(vals);
3418 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3423 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3424 const double *isAbsPtr=isAbs->getArray()->begin();
3425 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3426 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3429 else//meshdimension==1
3432 for(int i=0;i<nbOfCells;i++)
3434 int offset=connI[i];
3435 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3436 double n=INTERP_KERNEL::norm<2>(tmp);
3437 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3442 ret->setArray(array);
3444 ret->synchronizeTimeWithSupport();
3449 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3450 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3451 * and are normalized.
3452 * <br> \a this can be either
3453 * - a 2D mesh in 2D or 3D space or
3454 * - an 1D mesh in 2D space.
3456 * This method avoids building explicitly a part of \a this mesh to perform the work.
3457 * \param [in] begin - an array of cell ids of interest.
3458 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3459 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3460 * cells and one time. The caller is to delete this field using decrRef() as
3461 * it is no more needed.
3462 * \throw If the nodal connectivity of cells is not defined.
3463 * \throw If the coordinates array is not set.
3464 * \throw If the mesh dimension is not set.
3465 * \throw If the mesh and space dimension is not as specified above.
3466 * \sa buildOrthogonalField()
3468 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3469 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3471 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3473 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3474 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3475 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3476 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3477 std::size_t nbelems=std::distance(begin,end);
3478 int nbComp=getMeshDimension()+1;
3479 array->alloc((int)nbelems,nbComp);
3480 double *vals=array->getPointer();
3481 const int *connI=_nodal_connec_index->getConstPointer();
3482 const int *conn=_nodal_connec->getConstPointer();
3483 const double *coords=_coords->getConstPointer();
3484 if(getMeshDimension()==2)
3486 if(getSpaceDimension()==3)
3488 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3489 const double *locPtr=loc->getConstPointer();
3490 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3492 int offset=connI[*i];
3493 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3494 double n=INTERP_KERNEL::norm<3>(vals);
3495 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3500 for(std::size_t i=0;i<nbelems;i++)
3501 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3504 else//meshdimension==1
3507 for(const int *i=begin;i!=end;i++)
3509 int offset=connI[*i];
3510 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3511 double n=INTERP_KERNEL::norm<2>(tmp);
3512 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3517 ret->setArray(array);
3519 ret->synchronizeTimeWithSupport();
3524 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3525 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3526 * and are \b not normalized.
3527 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3528 * cells and one time. The caller is to delete this field using decrRef() as
3529 * it is no more needed.
3530 * \throw If the nodal connectivity of cells is not defined.
3531 * \throw If the coordinates array is not set.
3532 * \throw If \a this->getMeshDimension() != 1.
3533 * \throw If \a this mesh includes cells of type other than SEG2.
3535 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3537 if(getMeshDimension()!=1)
3538 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3539 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3540 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3541 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3542 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3543 int nbOfCells=getNumberOfCells();
3544 int spaceDim=getSpaceDimension();
3545 array->alloc(nbOfCells,spaceDim);
3546 double *pt=array->getPointer();
3547 const double *coo=getCoords()->getConstPointer();
3548 std::vector<int> conn;
3550 for(int i=0;i<nbOfCells;i++)
3553 getNodeIdsOfCell(i,conn);
3554 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3556 ret->setArray(array);
3558 ret->synchronizeTimeWithSupport();
3563 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3564 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3565 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3566 * from. If a result face is shared by two 3D cells, then the face in included twice in
3568 * \param [in] origin - 3 components of a point defining location of the plane.
3569 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3570 * must be greater than 1e-6.
3571 * \param [in] eps - half-thickness of the plane.
3572 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3573 * producing correspondent 2D cells. The caller is to delete this array
3574 * using decrRef() as it is no more needed.
3575 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3576 * not share the node coordinates array with \a this mesh. The caller is to
3577 * delete this mesh using decrRef() as it is no more needed.
3578 * \throw If the coordinates array is not set.
3579 * \throw If the nodal connectivity of cells is not defined.
3580 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3581 * \throw If magnitude of \a vec is less than 1e-6.
3582 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3583 * \throw If \a this includes quadratic cells.
3585 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3587 checkFullyDefined();
3588 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3589 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3590 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3591 if(candidates->empty())
3592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3593 std::vector<int> nodes;
3594 DataArrayInt *cellIds1D=0;
3595 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3596 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3597 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3598 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3599 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3601 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3602 revDesc2=0; revDescIndx2=0;
3603 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3604 revDesc1=0; revDescIndx1=0;
3605 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3606 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3608 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3609 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3611 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3612 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3613 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3614 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3615 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3617 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3618 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3619 if(cellIds2->empty())
3620 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3621 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3622 ret->setCoords(mDesc1->getCoords());
3623 ret->setConnectivity(conn,connI,true);
3624 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3629 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3630 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
3631 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3633 * \param [in] origin - 3 components of a point defining location of the plane.
3634 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3635 * must be greater than 1e-6.
3636 * \param [in] eps - half-thickness of the plane.
3637 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3638 * producing correspondent segments. The caller is to delete this array
3639 * using decrRef() as it is no more needed.
3640 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3641 * mesh in 3D space. This mesh does not share the node coordinates array with
3642 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3644 * \throw If the coordinates array is not set.
3645 * \throw If the nodal connectivity of cells is not defined.
3646 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3647 * \throw If magnitude of \a vec is less than 1e-6.
3648 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3649 * \throw If \a this includes quadratic cells.
3651 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3653 checkFullyDefined();
3654 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3655 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3656 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3657 if(candidates->empty())
3658 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3659 std::vector<int> nodes;
3660 DataArrayInt *cellIds1D=0;
3661 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3662 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3664 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3667 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3668 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3671 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3672 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3674 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3675 int ncellsSub=subMesh->getNumberOfCells();
3676 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3677 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3678 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3679 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3680 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3682 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3683 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3684 for(int i=0;i<ncellsSub;i++)
3686 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3688 if(cut3DSurf[i].first!=-2)
3690 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3691 connI->pushBackSilent(conn->getNumberOfTuples());
3692 cellIds2->pushBackSilent(i);
3696 int cellId3DSurf=cut3DSurf[i].second;
3697 int offset=nodalI[cellId3DSurf]+1;
3698 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3699 for(int j=0;j<nbOfEdges;j++)
3701 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3702 connI->pushBackSilent(conn->getNumberOfTuples());
3703 cellIds2->pushBackSilent(cellId3DSurf);
3708 if(cellIds2->empty())
3709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3710 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3711 ret->setCoords(mDesc1->getCoords());
3712 ret->setConnectivity(conn,connI,true);
3713 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3718 * Finds cells whose bounding boxes intersect a given plane.
3719 * \param [in] origin - 3 components of a point defining location of the plane.
3720 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3721 * must be greater than 1e-6.
3722 * \param [in] eps - half-thickness of the plane.
3723 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3724 * cells. The caller is to delete this array using decrRef() as it is no more
3726 * \throw If the coordinates array is not set.
3727 * \throw If the nodal connectivity of cells is not defined.
3728 * \throw If \a this->getSpaceDimension() != 3.
3729 * \throw If magnitude of \a vec is less than 1e-6.
3730 * \sa buildSlice3D()
3732 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3734 checkFullyDefined();
3735 if(getSpaceDimension()!=3)
3736 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3737 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3739 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3741 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3742 double angle=acos(vec[2]/normm);
3743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3747 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3748 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3749 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3751 mw->getBoundingBox(bbox);
3752 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3753 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3757 getBoundingBox(bbox);
3758 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3759 cellIds=getCellsInBoundingBox(bbox,eps);
3761 return cellIds.retn();
3765 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3766 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3767 * No consideration of coordinate is done by this method.
3768 * 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)
3769 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3771 bool MEDCouplingUMesh::isContiguous1D() const
3773 if(getMeshDimension()!=1)
3774 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3775 int nbCells=getNumberOfCells();
3777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3778 const int *connI=_nodal_connec_index->getConstPointer();
3779 const int *conn=_nodal_connec->getConstPointer();
3780 int ref=conn[connI[0]+2];
3781 for(int i=1;i<nbCells;i++)
3783 if(conn[connI[i]+1]!=ref)
3785 ref=conn[connI[i]+2];
3791 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3792 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3793 * \param pt reference point of the line
3794 * \param v normalized director vector of the line
3795 * \param eps max precision before throwing an exception
3796 * \param res output of size this->getNumberOfCells
3798 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3800 if(getMeshDimension()!=1)
3801 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3802 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3803 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3804 if(getSpaceDimension()!=3)
3805 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3806 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3807 const double *fPtr=f->getArray()->getConstPointer();
3809 for(int i=0;i<getNumberOfCells();i++)
3811 const double *tmp1=fPtr+3*i;
3812 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3813 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3814 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3815 double n1=INTERP_KERNEL::norm<3>(tmp);
3816 n1/=INTERP_KERNEL::norm<3>(tmp1);
3818 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3820 const double *coo=getCoords()->getConstPointer();
3821 for(int i=0;i<getNumberOfNodes();i++)
3823 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3824 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3825 res[i]=std::accumulate(tmp,tmp+3,0.);
3830 * 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.
3831 * \a this is expected to be a mesh so that its space dimension is equal to its
3832 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3833 * 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).
3835 * 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
3836 * 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).
3837 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3839 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3840 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3842 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3843 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3844 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3845 * \return the positive value of the distance.
3846 * \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
3848 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3850 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3852 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3853 if(meshDim!=spaceDim-1)
3854 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3855 if(meshDim!=2 && meshDim!=1)
3856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3857 checkFullyDefined();
3858 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3859 { 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()); }
3860 DataArrayInt *ret1=0;
3861 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3862 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3864 cellId=*ret1Safe->begin();
3865 return *ret0->begin();
3869 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3870 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3871 * 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
3872 * 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).
3873 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3875 * \a this is expected to be a mesh so that its space dimension is equal to its
3876 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3877 * 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).
3879 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3880 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3882 * \param [in] pts the list of points in which each tuple represents a point
3883 * \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.
3884 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3885 * \throw if number of components of \a pts is not equal to the space dimension.
3886 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3887 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3889 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3892 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3893 pts->checkAllocated();
3894 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3895 if(meshDim!=spaceDim-1)
3896 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3897 if(meshDim!=2 && meshDim!=1)
3898 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3899 if(pts->getNumberOfComponents()!=spaceDim)
3901 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3902 throw INTERP_KERNEL::Exception(oss.str().c_str());
3904 checkFullyDefined();
3905 int nbCells=getNumberOfCells();
3907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3908 int nbOfPts=pts->getNumberOfTuples();
3909 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3911 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3912 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3913 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3914 const double *bbox(bboxArr->begin());
3919 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3920 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3922 double x=std::numeric_limits<double>::max();
3923 std::vector<int> elems;
3924 myTree.getMinDistanceOfMax(ptsPtr,x);
3925 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3926 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3932 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3933 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3935 double x=std::numeric_limits<double>::max();
3936 std::vector<int> elems;
3937 myTree.getMinDistanceOfMax(ptsPtr,x);
3938 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3939 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3944 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3946 cellIds=ret1.retn();
3951 * \param [in] pt the start pointer (included) of the coordinates of the point
3952 * \param [in] cellIdsBg the start pointer (included) of cellIds
3953 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3954 * \param [in] nc nodal connectivity
3955 * \param [in] ncI nodal connectivity index
3956 * \param [in,out] ret0 the min distance between \a this and the external input point
3957 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3958 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3960 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)
3963 ret0=std::numeric_limits<double>::max();
3964 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3966 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3968 case INTERP_KERNEL::NORM_TRI3:
3970 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3972 { ret0=tmp; cellId=*zeCell; }
3975 case INTERP_KERNEL::NORM_QUAD4:
3976 case INTERP_KERNEL::NORM_POLYGON:
3978 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3980 { ret0=tmp; cellId=*zeCell; }
3984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3990 * \param [in] pt the start pointer (included) of the coordinates of the point
3991 * \param [in] cellIdsBg the start pointer (included) of cellIds
3992 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3993 * \param [in] nc nodal connectivity
3994 * \param [in] ncI nodal connectivity index
3995 * \param [in,out] ret0 the min distance between \a this and the external input point
3996 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3997 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3999 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)
4002 ret0=std::numeric_limits<double>::max();
4003 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4005 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4007 case INTERP_KERNEL::NORM_SEG2:
4009 std::size_t uselessEntry=0;
4010 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4013 { ret0=tmp; cellId=*zeCell; }
4017 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4023 * Finds cells in contact with a ball (i.e. a point with precision).
4024 * \warning This method is suitable if the caller intends to evaluate only one
4025 * point, for more points getCellsContainingPoints() is recommended as it is
4027 * \param [in] pos - array of coordinates of the ball central point.
4028 * \param [in] eps - ball radius.
4029 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4030 * if there are no such cells.
4031 * \throw If the coordinates array is not set.
4032 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4034 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4036 std::vector<int> elts;
4037 getCellsContainingPoint(pos,eps,elts);
4040 return elts.front();
4044 * Finds cells in contact with a ball (i.e. a point with precision).
4045 * \warning This method is suitable if the caller intends to evaluate only one
4046 * point, for more points getCellsContainingPoints() is recommended as it is
4048 * \param [in] pos - array of coordinates of the ball central point.
4049 * \param [in] eps - ball radius.
4050 * \param [out] elts - vector returning ids of the found cells. It is cleared
4051 * before inserting ids.
4052 * \throw If the coordinates array is not set.
4053 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4055 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4056 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4058 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4061 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4062 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4067 namespace ParaMEDMEM
4069 template<const int SPACEDIMM>
4073 static const int MY_SPACEDIM=SPACEDIMM;
4074 static const int MY_MESHDIM=8;
4075 typedef int MyConnType;
4076 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4078 // useless, but for windows compilation ...
4079 const double* getCoordinatesPtr() const { return 0; }
4080 const int* getConnectivityPtr() const { return 0; }
4081 const int* getConnectivityIndexPtr() const { return 0; }
4082 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4086 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4088 INTERP_KERNEL::Edge *ret=0;
4091 case INTERP_KERNEL::NORM_SEG2:
4093 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4096 case INTERP_KERNEL::NORM_SEG3:
4098 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4099 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4100 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4101 bool colinearity=inters.areColinears();
4102 delete e1; delete e2;
4104 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4106 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4107 mapp2[bg[2]].second=false;
4111 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4117 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4118 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4119 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4121 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4124 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.
4125 const double *coo=mDesc->getCoords()->getConstPointer();
4126 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4127 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4129 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4130 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4131 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4133 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4134 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4136 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4137 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4139 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4140 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4142 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4144 if((*it2).second.second)
4145 mapp[(*it2).second.first]=(*it2).first;
4146 ((*it2).second.first)->decrRef();
4151 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4155 int locId=nodeId-offset2;
4156 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4160 int locId=nodeId-offset1;
4161 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4163 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4166 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4167 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4168 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4170 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4172 int eltId1=abs(*desc1)-1;
4173 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4175 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4176 if(it==mappRev.end())
4178 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4189 template<int SPACEDIM>
4190 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4191 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4193 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4194 int *eltsIndexPtr(eltsIndex->getPointer());
4195 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4196 const double *bbox(bboxArr->begin());
4197 int nbOfCells=getNumberOfCells();
4198 const int *conn=_nodal_connec->getConstPointer();
4199 const int *connI=_nodal_connec_index->getConstPointer();
4200 double bb[2*SPACEDIM];
4201 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4202 for(int i=0;i<nbOfPoints;i++)
4204 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4205 for(int j=0;j<SPACEDIM;j++)
4207 bb[2*j]=pos[SPACEDIM*i+j];
4208 bb[2*j+1]=pos[SPACEDIM*i+j];
4210 std::vector<int> candidates;
4211 myTree.getIntersectingElems(bb,candidates);
4212 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4214 int sz=connI[(*iter)+1]-connI[*iter]-1;
4215 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4216 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4217 coords,conn+connI[*iter]+1,sz,eps))
4219 eltsIndexPtr[i+1]++;
4220 elts->pushBackSilent(*iter);
4226 * Finds cells in contact with several balls (i.e. points with precision).
4227 * This method is an extension of getCellContainingPoint() and
4228 * getCellsContainingPoint() for the case of multiple points.
4229 * \param [in] pos - an array of coordinates of points in full interlace mode :
4230 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4231 * this->getSpaceDimension() * \a nbOfPoints
4232 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4233 * \param [in] eps - radius of balls (i.e. the precision).
4234 * \param [out] elts - vector returning ids of found cells.
4235 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4236 * dividing cell ids in \a elts into groups each referring to one
4237 * point. Its every element (except the last one) is an index pointing to the
4238 * first id of a group of cells. For example cells in contact with the *i*-th
4239 * point are described by following range of indices:
4240 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4241 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4242 * Number of cells in contact with the *i*-th point is
4243 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4244 * \throw If the coordinates array is not set.
4245 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4247 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4248 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4250 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4253 int spaceDim=getSpaceDimension();
4254 int mDim=getMeshDimension();
4259 const double *coords=_coords->getConstPointer();
4260 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4267 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4269 else if(spaceDim==2)
4273 const double *coords=_coords->getConstPointer();
4274 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4277 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4279 else if(spaceDim==1)
4283 const double *coords=_coords->getConstPointer();
4284 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4287 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4290 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4294 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4295 * least two its edges intersect each other anywhere except their extremities. An
4296 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4297 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4298 * cleared before filling in.
4299 * \param [in] eps - precision.
4300 * \throw If \a this->getMeshDimension() != 2.
4301 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4303 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4305 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4306 if(getMeshDimension()!=2)
4307 throw INTERP_KERNEL::Exception(msg);
4308 int spaceDim=getSpaceDimension();
4309 if(spaceDim!=2 && spaceDim!=3)
4310 throw INTERP_KERNEL::Exception(msg);
4311 const int *conn=_nodal_connec->getConstPointer();
4312 const int *connI=_nodal_connec_index->getConstPointer();
4313 int nbOfCells=getNumberOfCells();
4314 std::vector<double> cell2DinS2;
4315 for(int i=0;i<nbOfCells;i++)
4317 int offset=connI[i];
4318 int nbOfNodesForCell=connI[i+1]-offset-1;
4319 if(nbOfNodesForCell<=3)
4321 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4322 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4323 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4330 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4332 * 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.
4333 * 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.
4335 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4336 * This convex envelop is computed using Jarvis march algorithm.
4337 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4338 * 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)
4339 * 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.
4341 * \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.
4343 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4345 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4347 checkFullyDefined();
4348 const double *coords=getCoords()->getConstPointer();
4349 int nbOfCells=getNumberOfCells();
4350 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4351 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4353 int *workIndexOut=nodalConnecIndexOut->getPointer();
4355 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4356 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4357 std::set<INTERP_KERNEL::NormalizedCellType> types;
4358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4359 isChanged->alloc(0,1);
4360 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4362 int pos=nodalConnecOut->getNumberOfTuples();
4363 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4364 isChanged->pushBackSilent(i);
4365 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4366 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4368 if(isChanged->empty())
4370 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4372 return isChanged.retn();
4376 * This method is \b NOT const because it can modify \a this.
4377 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4378 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4379 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4380 * \b 1 for translation and rotation around point of 'mesh1D'.
4381 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4383 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4385 checkFullyDefined();
4386 mesh1D->checkFullyDefined();
4387 if(!mesh1D->isContiguous1D())
4388 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4389 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4390 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4391 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4392 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4393 if(mesh1D->getMeshDimension()!=1)
4394 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4396 if(isPresenceOfQuadratic())
4398 if(mesh1D->isFullyQuadratic())
4401 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4404 int oldNbOfNodes=getNumberOfNodes();
4405 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4410 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4415 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4419 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4421 setCoords(newCoords);
4422 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4428 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4429 * If it is not the case an exception will be thrown.
4430 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4431 * intersection of plane defined by ('origin','vec').
4432 * This method has one in/out parameter : 'cut3DCurve'.
4433 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4434 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4435 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4436 * This method will throw an exception if \a this contains a non linear segment.
4438 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4440 checkFullyDefined();
4441 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4442 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4443 int ncells=getNumberOfCells();
4444 int nnodes=getNumberOfNodes();
4445 double vec2[3],vec3[3],vec4[3];
4446 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4448 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4449 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4450 const int *conn=_nodal_connec->getConstPointer();
4451 const int *connI=_nodal_connec_index->getConstPointer();
4452 const double *coo=_coords->getConstPointer();
4453 std::vector<double> addCoo;
4454 for(int i=0;i<ncells;i++)
4456 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4458 if(cut3DCurve[i]==-2)
4460 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4461 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];
4462 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4463 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4464 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4466 const double *st2=coo+3*st;
4467 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4468 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]));
4469 if(pos>eps && pos<1-eps)
4471 int nNode=((int)addCoo.size())/3;
4472 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4473 addCoo.insert(addCoo.end(),vec4,vec4+3);
4474 cut3DCurve[i]=nnodes+nNode;
4480 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4484 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4485 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4486 coo2->alloc(newNbOfNodes,3);
4487 double *tmp=coo2->getPointer();
4488 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4489 std::copy(addCoo.begin(),addCoo.end(),tmp);
4490 DataArrayDouble::SetArrayIn(coo2,_coords);
4495 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4496 * \param mesh1D is the input 1D mesh used for translation computation.
4497 * \return newCoords new coords filled by this method.
4499 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4501 int oldNbOfNodes=getNumberOfNodes();
4502 int nbOf1DCells=mesh1D->getNumberOfCells();
4503 int spaceDim=getSpaceDimension();
4504 DataArrayDouble *ret=DataArrayDouble::New();
4505 std::vector<bool> isQuads;
4506 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4507 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4508 double *retPtr=ret->getPointer();
4509 const double *coords=getCoords()->getConstPointer();
4510 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4512 std::vector<double> c;
4516 for(int i=0;i<nbOf1DCells;i++)
4519 mesh1D->getNodeIdsOfCell(i,v);
4521 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4522 mesh1D->getCoordinatesOfNode(v[0],c);
4523 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4524 for(int j=0;j<oldNbOfNodes;j++)
4525 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4529 mesh1D->getCoordinatesOfNode(v[1],c);
4530 mesh1D->getCoordinatesOfNode(v[0],c);
4531 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4532 for(int j=0;j<oldNbOfNodes;j++)
4533 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4536 ret->copyStringInfoFrom(*getCoords());
4541 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4542 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4543 * \return newCoords new coords filled by this method.
4545 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4547 if(mesh1D->getSpaceDimension()==2)
4548 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4549 if(mesh1D->getSpaceDimension()==3)
4550 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4551 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4555 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4556 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4557 * \return newCoords new coords filled by this method.
4559 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4562 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4563 int oldNbOfNodes=getNumberOfNodes();
4564 int nbOf1DCells=mesh1D->getNumberOfCells();
4566 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4567 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4568 int nbOfLevsInVec=nbOf1DCells+1;
4569 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4570 double *retPtr=ret->getPointer();
4571 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4572 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4573 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4574 tmp->setCoords(tmp2);
4575 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4576 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4577 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4578 for(int i=1;i<nbOfLevsInVec;i++)
4580 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4581 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4582 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4583 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4584 tmp->translate(vec);
4585 double tmp3[2],radius,alpha,alpha0;
4586 const double *p0=i+1<nbOfLevsInVec?begin:third;
4587 const double *p1=i+1<nbOfLevsInVec?end:begin;
4588 const double *p2=i+1<nbOfLevsInVec?third:end;
4589 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4590 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]);
4591 double angle=acos(cosangle/(radius*radius));
4592 tmp->rotate(end,0,angle);
4593 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4599 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4600 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4601 * \return newCoords new coords filled by this method.
4603 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4606 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4607 int oldNbOfNodes=getNumberOfNodes();
4608 int nbOf1DCells=mesh1D->getNumberOfCells();
4610 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4611 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4612 int nbOfLevsInVec=nbOf1DCells+1;
4613 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4614 double *retPtr=ret->getPointer();
4615 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4616 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4617 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4618 tmp->setCoords(tmp2);
4619 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4620 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4621 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4622 for(int i=1;i<nbOfLevsInVec;i++)
4624 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4625 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4626 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4627 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4628 tmp->translate(vec);
4629 double tmp3[2],radius,alpha,alpha0;
4630 const double *p0=i+1<nbOfLevsInVec?begin:third;
4631 const double *p1=i+1<nbOfLevsInVec?end:begin;
4632 const double *p2=i+1<nbOfLevsInVec?third:end;
4633 double vecPlane[3]={
4634 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4635 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4636 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4638 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4641 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4642 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4643 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4645 double c2=cos(asin(s2));
4647 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4648 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4649 {-vec2[1]*s2, vec2[0]*s2, c2}
4651 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]};
4652 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]};
4653 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]};
4654 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4655 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]);
4656 double angle=acos(cosangle/(radius*radius));
4657 tmp->rotate(end,vecPlane,angle);
4660 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4666 * This method is private because not easy to use for end user. This method is const contrary to
4667 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4668 * the coords sorted slice by slice.
4669 * \param isQuad specifies presence of quadratic cells.
4671 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4673 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4674 int nbOf2DCells=getNumberOfCells();
4675 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4676 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4677 const int *conn=_nodal_connec->getConstPointer();
4678 const int *connI=_nodal_connec_index->getConstPointer();
4679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4680 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4681 newConnI->alloc(nbOf3DCells+1,1);
4682 int *newConnIPtr=newConnI->getPointer();
4684 std::vector<int> newc;
4685 for(int j=0;j<nbOf2DCells;j++)
4687 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4688 *newConnIPtr++=(int)newc.size();
4690 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4691 int *newConnPtr=newConn->getPointer();
4692 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4693 newConnIPtr=newConnI->getPointer();
4694 for(int iz=0;iz<nbOf1DCells;iz++)
4697 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4698 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4700 int icell=(int)(iter-newc.begin());
4701 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4704 *newConnPtr=(*iter)+iz*deltaPerLev;
4709 *newConnPtr=(*iter);
4712 ret->setConnectivity(newConn,newConnI,true);
4713 ret->setCoords(getCoords());
4718 * Checks if \a this mesh is constituted by only quadratic cells.
4719 * \return bool - \c true if there are only 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::isFullyQuadratic() 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 * Checks if \a this mesh includes any quadratic cell.
4739 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4740 * \throw If the coordinates array is not set.
4741 * \throw If the nodal connectivity of cells is not defined.
4743 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4745 checkFullyDefined();
4747 int nbOfCells=getNumberOfCells();
4748 for(int i=0;i<nbOfCells && !ret;i++)
4750 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4751 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4752 ret=cm.isQuadratic();
4758 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4759 * this mesh, it remains unchanged.
4760 * \throw If the coordinates array is not set.
4761 * \throw If the nodal connectivity of cells is not defined.
4763 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4765 checkFullyDefined();
4766 int nbOfCells=getNumberOfCells();
4768 const int *iciptr=_nodal_connec_index->getConstPointer();
4769 for(int i=0;i<nbOfCells;i++)
4771 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4772 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4773 if(cm.isQuadratic())
4775 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4776 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4777 if(!cml.isDynamic())
4778 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4780 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4785 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4787 const int *icptr=_nodal_connec->getConstPointer();
4788 newConn->alloc(getMeshLength()-delta,1);
4789 newConnI->alloc(nbOfCells+1,1);
4790 int *ocptr=newConn->getPointer();
4791 int *ociptr=newConnI->getPointer();
4794 for(int i=0;i<nbOfCells;i++,ociptr++)
4796 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4797 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4798 if(!cm.isQuadratic())
4800 _types.insert(type);
4801 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4802 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4806 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4807 _types.insert(typel);
4808 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4809 int newNbOfNodes=cml.getNumberOfNodes();
4811 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4812 *ocptr++=(int)typel;
4813 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4814 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4817 setConnectivity(newConn,newConnI,false);
4821 * This method converts all linear cell in \a this to quadratic one.
4822 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4823 * 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)
4824 * 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.
4825 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4826 * end of the existing coordinates.
4828 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4829 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4830 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4832 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4834 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4836 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4838 DataArrayInt *conn=0,*connI=0;
4839 DataArrayDouble *coords=0;
4840 std::set<INTERP_KERNEL::NormalizedCellType> types;
4841 checkFullyDefined();
4842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4843 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4844 int meshDim=getMeshDimension();
4845 switch(conversionType)
4851 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4852 connSafe=conn; connISafe=connI; coordsSafe=coords;
4855 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4856 connSafe=conn; connISafe=connI; coordsSafe=coords;
4859 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4860 connSafe=conn; connISafe=connI; coordsSafe=coords;
4863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4871 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4872 connSafe=conn; connISafe=connI; coordsSafe=coords;
4875 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4876 connSafe=conn; connISafe=connI; coordsSafe=coords;
4879 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4880 connSafe=conn; connISafe=connI; coordsSafe=coords;
4883 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4890 setConnectivity(connSafe,connISafe,false);
4892 setCoords(coordsSafe);
4897 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4898 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4899 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4901 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4903 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4907 int nbOfCells=getNumberOfCells();
4908 int nbOfNodes=getNumberOfNodes();
4909 const int *cPtr=_nodal_connec->getConstPointer();
4910 const int *icPtr=_nodal_connec_index->getConstPointer();
4911 int lastVal=0,offset=nbOfNodes;
4912 for(int i=0;i<nbOfCells;i++,icPtr++)
4914 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4915 if(type==INTERP_KERNEL::NORM_SEG2)
4917 types.insert(INTERP_KERNEL::NORM_SEG3);
4918 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4919 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4920 newConn->pushBackSilent(offset++);
4922 newConnI->pushBackSilent(lastVal);
4923 ret->pushBackSilent(i);
4928 lastVal+=(icPtr[1]-icPtr[0]);
4929 newConnI->pushBackSilent(lastVal);
4930 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4933 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4934 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4938 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
4940 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4944 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4945 DataArrayInt *conn1D=0,*conn1DI=0;
4946 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4947 DataArrayDouble *coordsTmp=0;
4948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4949 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4951 const int *c1DPtr=conn1D->begin();
4952 const int *c1DIPtr=conn1DI->begin();
4953 int nbOfCells=getNumberOfCells();
4954 const int *cPtr=_nodal_connec->getConstPointer();
4955 const int *icPtr=_nodal_connec_index->getConstPointer();
4957 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4959 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4960 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4961 if(!cm.isQuadratic())
4963 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4964 types.insert(typ2); newConn->pushBackSilent(typ2);
4965 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4966 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4967 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4968 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4969 newConnI->pushBackSilent(lastVal);
4970 ret->pushBackSilent(i);
4975 lastVal+=(icPtr[1]-icPtr[0]);
4976 newConnI->pushBackSilent(lastVal);
4977 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4980 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4985 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4986 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4987 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4989 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4992 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4993 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4994 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4997 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5000 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5002 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5003 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5004 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5006 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5007 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5008 DataArrayInt *conn1D=0,*conn1DI=0;
5009 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5010 DataArrayDouble *coordsTmp=0;
5011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5012 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5014 const int *c1DPtr=conn1D->begin();
5015 const int *c1DIPtr=conn1DI->begin();
5016 int nbOfCells=getNumberOfCells();
5017 const int *cPtr=_nodal_connec->getConstPointer();
5018 const int *icPtr=_nodal_connec_index->getConstPointer();
5019 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5020 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5022 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5023 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5024 if(!cm.isQuadratic())
5026 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5027 types.insert(typ2); newConn->pushBackSilent(typ2);
5028 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5029 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5030 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5031 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5032 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5033 newConnI->pushBackSilent(lastVal);
5034 ret->pushBackSilent(i);
5039 lastVal+=(icPtr[1]-icPtr[0]);
5040 newConnI->pushBackSilent(lastVal);
5041 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5044 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5045 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5050 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5051 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5052 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5054 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5057 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5058 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5061 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5064 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5066 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5072 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5073 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5074 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5075 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5076 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5077 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5078 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5079 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5080 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5081 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5082 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5083 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5084 int nbOfCells=getNumberOfCells();
5085 const int *cPtr=_nodal_connec->getConstPointer();
5086 const int *icPtr=_nodal_connec_index->getConstPointer();
5087 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5088 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5090 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5091 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5092 if(!cm.isQuadratic())
5094 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5095 if(typ2==INTERP_KERNEL::NORM_ERROR)
5097 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5098 throw INTERP_KERNEL::Exception(oss.str().c_str());
5100 types.insert(typ2); newConn->pushBackSilent(typ2);
5101 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5102 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5103 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5104 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5106 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5107 int tmpPos=newConn->getNumberOfTuples();
5108 newConn->pushBackSilent(nodeId2);
5109 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5111 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5112 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5113 newConnI->pushBackSilent(lastVal);
5114 ret->pushBackSilent(i);
5119 lastVal+=(icPtr[1]-icPtr[0]);
5120 newConnI->pushBackSilent(lastVal);
5121 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5126 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5127 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5128 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5129 int *c=newConn->getPointer();
5130 const int *cI(newConnI->begin());
5131 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5132 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5133 offset=coordsTmp2Safe->getNumberOfTuples();
5134 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5135 c[cI[(*elt)+1]-1]+=offset;
5136 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5141 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5142 * so that the number of cells remains the same. Quadratic faces are converted to
5143 * polygons. This method works only for 2D meshes in
5144 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5145 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5146 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5147 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5148 * a polylinized edge constituting the input polygon.
5149 * \throw If the coordinates array is not set.
5150 * \throw If the nodal connectivity of cells is not defined.
5151 * \throw If \a this->getMeshDimension() != 2.
5152 * \throw If \a this->getSpaceDimension() != 2.
5154 void MEDCouplingUMesh::tessellate2D(double eps)
5156 checkFullyDefined();
5157 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5158 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5159 double epsa=fabs(eps);
5160 if(epsa<std::numeric_limits<double>::min())
5161 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 !");
5162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5166 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5167 revDesc1=0; revDescIndx1=0;
5168 mDesc->tessellate2DCurve(eps);
5169 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5170 setCoords(mDesc->getCoords());
5174 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5175 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5176 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5177 * a sub-divided edge.
5178 * \throw If the coordinates array is not set.
5179 * \throw If the nodal connectivity of cells is not defined.
5180 * \throw If \a this->getMeshDimension() != 1.
5181 * \throw If \a this->getSpaceDimension() != 2.
5183 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5185 checkFullyDefined();
5186 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5187 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5188 double epsa=fabs(eps);
5189 if(epsa<std::numeric_limits<double>::min())
5190 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 !");
5191 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5192 int nbCells=getNumberOfCells();
5193 int nbNodes=getNumberOfNodes();
5194 const int *conn=_nodal_connec->getConstPointer();
5195 const int *connI=_nodal_connec_index->getConstPointer();
5196 const double *coords=_coords->getConstPointer();
5197 std::vector<double> addCoo;
5198 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5200 newConnI->alloc(nbCells+1,1);
5201 int *newConnIPtr=newConnI->getPointer();
5204 INTERP_KERNEL::Node *tmp2[3];
5205 std::set<INTERP_KERNEL::NormalizedCellType> types;
5206 for(int i=0;i<nbCells;i++,newConnIPtr++)
5208 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5209 if(cm.isQuadratic())
5210 {//assert(connI[i+1]-connI[i]-1==3)
5211 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5212 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5213 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5214 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5215 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5218 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5219 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5221 newConnIPtr[1]=(int)newConn.size();
5225 types.insert(INTERP_KERNEL::NORM_SEG2);
5226 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5227 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5228 newConnIPtr[1]=newConnIPtr[0]+3;
5233 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5234 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5235 newConnIPtr[1]=newConnIPtr[0]+3;
5238 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5241 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5243 newConnArr->alloc((int)newConn.size(),1);
5244 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5245 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5246 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5247 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5248 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5249 std::copy(addCoo.begin(),addCoo.end(),work);
5250 DataArrayDouble::SetArrayIn(newCoords,_coords);
5255 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5256 * In addition, returns an array mapping new cells to old ones. <br>
5257 * This method typically increases the number of cells in \a this mesh
5258 * but the number of nodes remains \b unchanged.
5259 * That's why the 3D splitting policies
5260 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5261 * \param [in] policy - specifies a pattern used for splitting.
5262 * The semantic of \a policy is:
5263 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5264 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5265 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5266 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5267 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5268 * an id of old cell producing it. The caller is to delete this array using
5269 * decrRef() as it is no more needed.
5270 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5271 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5272 * and \a this->getMeshDimension() != 3.
5273 * \throw If \a policy is not one of the four discussed above.
5274 * \throw If the nodal connectivity of cells is not defined.
5275 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5277 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5282 return simplexizePol0();
5284 return simplexizePol1();
5285 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5286 return simplexizePlanarFace5();
5287 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5288 return simplexizePlanarFace6();
5290 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)");
5295 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5296 * - 1D: INTERP_KERNEL::NORM_SEG2
5297 * - 2D: INTERP_KERNEL::NORM_TRI3
5298 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5300 * This method is useful for users that need to use P1 field services as
5301 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5302 * All these methods need mesh support containing only simplex cells.
5303 * \return bool - \c true if there are only simplex cells in \a this mesh.
5304 * \throw If the coordinates array is not set.
5305 * \throw If the nodal connectivity of cells is not defined.
5306 * \throw If \a this->getMeshDimension() < 1.
5308 bool MEDCouplingUMesh::areOnlySimplexCells() const
5310 checkFullyDefined();
5311 int mdim=getMeshDimension();
5312 if(mdim<1 || mdim>3)
5313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5314 int nbCells=getNumberOfCells();
5315 const int *conn=_nodal_connec->getConstPointer();
5316 const int *connI=_nodal_connec_index->getConstPointer();
5317 for(int i=0;i<nbCells;i++)
5319 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5327 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5329 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5331 checkConnectivityFullyDefined();
5332 if(getMeshDimension()!=2)
5333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5334 int nbOfCells=getNumberOfCells();
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5336 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5337 ret->alloc(nbOfCells+nbOfCutCells,1);
5338 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5339 int *retPt=ret->getPointer();
5340 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5342 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5343 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5344 int *pt=newConn->getPointer();
5345 int *ptI=newConnI->getPointer();
5347 const int *oldc=_nodal_connec->getConstPointer();
5348 const int *ci=_nodal_connec_index->getConstPointer();
5349 for(int i=0;i<nbOfCells;i++,ci++)
5351 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5353 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5354 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5355 pt=std::copy(tmp,tmp+8,pt);
5364 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5365 ptI[1]=ptI[0]+ci[1]-ci[0];
5370 _nodal_connec->decrRef();
5371 _nodal_connec=newConn.retn();
5372 _nodal_connec_index->decrRef();
5373 _nodal_connec_index=newConnI.retn();
5380 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5382 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5384 checkConnectivityFullyDefined();
5385 if(getMeshDimension()!=2)
5386 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5387 int nbOfCells=getNumberOfCells();
5388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5389 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5390 ret->alloc(nbOfCells+nbOfCutCells,1);
5391 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5392 int *retPt=ret->getPointer();
5393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5395 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5396 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5397 int *pt=newConn->getPointer();
5398 int *ptI=newConnI->getPointer();
5400 const int *oldc=_nodal_connec->getConstPointer();
5401 const int *ci=_nodal_connec_index->getConstPointer();
5402 for(int i=0;i<nbOfCells;i++,ci++)
5404 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5406 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5407 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5408 pt=std::copy(tmp,tmp+8,pt);
5417 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5418 ptI[1]=ptI[0]+ci[1]-ci[0];
5423 _nodal_connec->decrRef();
5424 _nodal_connec=newConn.retn();
5425 _nodal_connec_index->decrRef();
5426 _nodal_connec_index=newConnI.retn();
5433 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5435 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5437 checkConnectivityFullyDefined();
5438 if(getMeshDimension()!=3)
5439 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5440 int nbOfCells=getNumberOfCells();
5441 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5442 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5443 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5444 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5445 int *retPt=ret->getPointer();
5446 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5447 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5448 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5449 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5450 int *pt=newConn->getPointer();
5451 int *ptI=newConnI->getPointer();
5453 const int *oldc=_nodal_connec->getConstPointer();
5454 const int *ci=_nodal_connec_index->getConstPointer();
5455 for(int i=0;i<nbOfCells;i++,ci++)
5457 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5459 for(int j=0;j<5;j++,pt+=5,ptI++)
5461 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5462 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];
5469 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5470 ptI[1]=ptI[0]+ci[1]-ci[0];
5475 _nodal_connec->decrRef();
5476 _nodal_connec=newConn.retn();
5477 _nodal_connec_index->decrRef();
5478 _nodal_connec_index=newConnI.retn();
5485 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5487 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5489 checkConnectivityFullyDefined();
5490 if(getMeshDimension()!=3)
5491 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5492 int nbOfCells=getNumberOfCells();
5493 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5494 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5495 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5496 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5497 int *retPt=ret->getPointer();
5498 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5499 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5500 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5501 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5502 int *pt=newConn->getPointer();
5503 int *ptI=newConnI->getPointer();
5505 const int *oldc=_nodal_connec->getConstPointer();
5506 const int *ci=_nodal_connec_index->getConstPointer();
5507 for(int i=0;i<nbOfCells;i++,ci++)
5509 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5511 for(int j=0;j<6;j++,pt+=5,ptI++)
5513 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5514 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];
5521 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5522 ptI[1]=ptI[0]+ci[1]-ci[0];
5527 _nodal_connec->decrRef();
5528 _nodal_connec=newConn.retn();
5529 _nodal_connec_index->decrRef();
5530 _nodal_connec_index=newConnI.retn();
5537 * 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.
5538 * This method completly ignore coordinates.
5539 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5540 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5541 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5542 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5544 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5546 checkFullyDefined();
5547 if(getMeshDimension()!=2)
5548 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5549 int nbOfCells=getNumberOfCells();
5550 int *connI=_nodal_connec_index->getPointer();
5552 for(int i=0;i<nbOfCells;i++,connI++)
5554 int offset=descIndex[i];
5555 int nbOfEdges=descIndex[i+1]-offset;
5557 bool ddirect=desc[offset+nbOfEdges-1]>0;
5558 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5559 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5560 for(int j=0;j<nbOfEdges;j++)
5562 bool direct=desc[offset+j]>0;
5563 int edgeId=std::abs(desc[offset+j])-1;
5564 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5566 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5567 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5568 int ref2=direct?id1:id2;
5571 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5572 newConnLgth+=nbOfSubNodes-1;
5577 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5578 throw INTERP_KERNEL::Exception(oss.str().c_str());
5583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5586 newConnLgth++;//+1 is for cell type
5587 connI[1]=newConnLgth;
5590 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5591 newConn->alloc(newConnLgth,1);
5592 int *work=newConn->getPointer();
5593 for(int i=0;i<nbOfCells;i++)
5595 *work++=INTERP_KERNEL::NORM_POLYGON;
5596 int offset=descIndex[i];
5597 int nbOfEdges=descIndex[i+1]-offset;
5598 for(int j=0;j<nbOfEdges;j++)
5600 bool direct=desc[offset+j]>0;
5601 int edgeId=std::abs(desc[offset+j])-1;
5603 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5606 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5607 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5608 work=std::copy(it,it+nbOfSubNodes-1,work);
5612 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5615 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5619 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5620 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5621 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5622 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5623 * so it can be useful to call mergeNodes() before calling this method.
5624 * \throw If \a this->getMeshDimension() <= 1.
5625 * \throw If the coordinates array is not set.
5626 * \throw If the nodal connectivity of cells is not defined.
5628 void MEDCouplingUMesh::convertDegeneratedCells()
5630 checkFullyDefined();
5631 if(getMeshDimension()<=1)
5632 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5633 int nbOfCells=getNumberOfCells();
5636 int initMeshLgth=getMeshLength();
5637 int *conn=_nodal_connec->getPointer();
5638 int *index=_nodal_connec_index->getPointer();
5642 for(int i=0;i<nbOfCells;i++)
5644 lgthOfCurCell=index[i+1]-posOfCurCell;
5645 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5647 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5648 conn+newPos+1,newLgth);
5649 conn[newPos]=newType;
5651 posOfCurCell=index[i+1];
5654 if(newPos!=initMeshLgth)
5655 _nodal_connec->reAlloc(newPos);
5660 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5661 * A cell is considered to be oriented correctly if an angle between its
5662 * normal vector and a given vector is less than \c PI / \c 2.
5663 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5665 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5667 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5668 * is not cleared before filling in.
5669 * \throw If \a this->getMeshDimension() != 2.
5670 * \throw If \a this->getSpaceDimension() != 3.
5672 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5673 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5675 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5677 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5678 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5679 int nbOfCells=getNumberOfCells();
5680 const int *conn=_nodal_connec->getConstPointer();
5681 const int *connI=_nodal_connec_index->getConstPointer();
5682 const double *coordsPtr=_coords->getConstPointer();
5683 for(int i=0;i<nbOfCells;i++)
5685 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5686 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5688 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5689 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5696 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5697 * considered to be oriented correctly if an angle between its normal vector and a
5698 * given vector is less than \c PI / \c 2.
5699 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5701 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5703 * \throw If \a this->getMeshDimension() != 2.
5704 * \throw If \a this->getSpaceDimension() != 3.
5706 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5707 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5709 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5711 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5712 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5713 int nbOfCells=getNumberOfCells();
5714 int *conn=_nodal_connec->getPointer();
5715 const int *connI=_nodal_connec_index->getConstPointer();
5716 const double *coordsPtr=_coords->getConstPointer();
5717 bool isModified=false;
5718 for(int i=0;i<nbOfCells;i++)
5720 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5721 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5723 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5724 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5729 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5730 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5731 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5735 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5736 std::vector<int> tmp0(sz-1),tmp1(sz);
5737 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5738 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5739 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5740 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5746 _nodal_connec->declareAsNew();
5751 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5752 * oriented facets. The normal vector of the facet should point out of the cell.
5753 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5754 * is not cleared before filling in.
5755 * \throw If \a this->getMeshDimension() != 3.
5756 * \throw If \a this->getSpaceDimension() != 3.
5757 * \throw If the coordinates array is not set.
5758 * \throw If the nodal connectivity of cells is not defined.
5760 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5761 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5763 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5765 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5766 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5767 int nbOfCells=getNumberOfCells();
5768 const int *conn=_nodal_connec->getConstPointer();
5769 const int *connI=_nodal_connec_index->getConstPointer();
5770 const double *coordsPtr=_coords->getConstPointer();
5771 for(int i=0;i<nbOfCells;i++)
5773 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5774 if(type==INTERP_KERNEL::NORM_POLYHED)
5776 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5783 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5785 * \throw If \a this->getMeshDimension() != 3.
5786 * \throw If \a this->getSpaceDimension() != 3.
5787 * \throw If the coordinates array is not set.
5788 * \throw If the nodal connectivity of cells is not defined.
5789 * \throw If the reparation fails.
5791 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5792 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5793 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5795 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5797 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5798 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5799 int nbOfCells=getNumberOfCells();
5800 int *conn=_nodal_connec->getPointer();
5801 const int *connI=_nodal_connec_index->getConstPointer();
5802 const double *coordsPtr=_coords->getConstPointer();
5803 for(int i=0;i<nbOfCells;i++)
5805 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5806 if(type==INTERP_KERNEL::NORM_POLYHED)
5810 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5811 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5813 catch(INTERP_KERNEL::Exception& e)
5815 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5816 throw INTERP_KERNEL::Exception(oss.str().c_str());
5824 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5825 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5826 * according to which the first facet of the cell should be oriented to have the normal vector
5827 * pointing out of cell.
5828 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5829 * cells. The caller is to delete this array using decrRef() as it is no more
5831 * \throw If \a this->getMeshDimension() != 3.
5832 * \throw If \a this->getSpaceDimension() != 3.
5833 * \throw If the coordinates array is not set.
5834 * \throw If the nodal connectivity of cells is not defined.
5836 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5837 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5838 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5840 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5842 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5843 if(getMeshDimension()!=3)
5844 throw INTERP_KERNEL::Exception(msg);
5845 int spaceDim=getSpaceDimension();
5847 throw INTERP_KERNEL::Exception(msg);
5849 int nbOfCells=getNumberOfCells();
5850 int *conn=_nodal_connec->getPointer();
5851 const int *connI=_nodal_connec_index->getConstPointer();
5852 const double *coo=getCoords()->getConstPointer();
5853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5854 for(int i=0;i<nbOfCells;i++)
5856 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5857 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5859 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5861 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5862 cells->pushBackSilent(i);
5866 return cells.retn();
5870 * This method is a faster method to correct orientation of all 3D cells in \a this.
5871 * 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.
5872 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5874 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5875 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5877 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5879 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5880 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5881 int nbOfCells=getNumberOfCells();
5882 int *conn=_nodal_connec->getPointer();
5883 const int *connI=_nodal_connec_index->getConstPointer();
5884 const double *coordsPtr=_coords->getConstPointer();
5885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5886 for(int i=0;i<nbOfCells;i++)
5888 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5891 case INTERP_KERNEL::NORM_TETRA4:
5893 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5895 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5896 ret->pushBackSilent(i);
5900 case INTERP_KERNEL::NORM_PYRA5:
5902 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5904 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5905 ret->pushBackSilent(i);
5909 case INTERP_KERNEL::NORM_PENTA6:
5910 case INTERP_KERNEL::NORM_HEXA8:
5911 case INTERP_KERNEL::NORM_HEXGP12:
5913 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5915 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5916 ret->pushBackSilent(i);
5920 case INTERP_KERNEL::NORM_POLYHED:
5922 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5924 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5925 ret->pushBackSilent(i);
5930 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 !");
5938 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5939 * If it is not the case an exception will be thrown.
5940 * This method is fast because the first cell of \a this is used to compute the plane.
5941 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5942 * \param pos output of size at least 3 used to store a point owned of searched plane.
5944 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5946 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5947 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5948 const int *conn=_nodal_connec->getConstPointer();
5949 const int *connI=_nodal_connec_index->getConstPointer();
5950 const double *coordsPtr=_coords->getConstPointer();
5951 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5952 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5956 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5957 * cells. Currently cells of the following types are treated:
5958 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5959 * For a cell of other type an exception is thrown.
5960 * Space dimension of a 2D mesh can be either 2 or 3.
5961 * The Edge Ratio of a cell \f$t\f$ is:
5962 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5963 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5964 * the smallest edge lengths of \f$t\f$.
5965 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5966 * cells and one time, lying on \a this mesh. The caller is to delete this
5967 * field using decrRef() as it is no more needed.
5968 * \throw If the coordinates array is not set.
5969 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5970 * \throw If the connectivity data array has more than one component.
5971 * \throw If the connectivity data array has a named component.
5972 * \throw If the connectivity index data array has more than one component.
5973 * \throw If the connectivity index data array has a named component.
5974 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5975 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5976 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5978 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5981 int spaceDim=getSpaceDimension();
5982 int meshDim=getMeshDimension();
5983 if(spaceDim!=2 && spaceDim!=3)
5984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5985 if(meshDim!=2 && meshDim!=3)
5986 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5987 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5989 int nbOfCells=getNumberOfCells();
5990 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5991 arr->alloc(nbOfCells,1);
5992 double *pt=arr->getPointer();
5993 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5994 const int *conn=_nodal_connec->getConstPointer();
5995 const int *connI=_nodal_connec_index->getConstPointer();
5996 const double *coo=_coords->getConstPointer();
5998 for(int i=0;i<nbOfCells;i++,pt++)
6000 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6003 case INTERP_KERNEL::NORM_TRI3:
6005 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6006 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6009 case INTERP_KERNEL::NORM_QUAD4:
6011 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6012 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6015 case INTERP_KERNEL::NORM_TETRA4:
6017 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6018 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6022 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6024 conn+=connI[i+1]-connI[i];
6026 ret->setName("EdgeRatio");
6027 ret->synchronizeTimeWithSupport();
6032 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6033 * cells. Currently cells of the following types are treated:
6034 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6035 * For a cell of other type an exception is thrown.
6036 * Space dimension of a 2D mesh can be either 2 or 3.
6037 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6038 * cells and one time, lying on \a this mesh. The caller is to delete this
6039 * field using decrRef() as it is no more needed.
6040 * \throw If the coordinates array is not set.
6041 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6042 * \throw If the connectivity data array has more than one component.
6043 * \throw If the connectivity data array has a named component.
6044 * \throw If the connectivity index data array has more than one component.
6045 * \throw If the connectivity index data array has a named component.
6046 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6047 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6048 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6050 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6053 int spaceDim=getSpaceDimension();
6054 int meshDim=getMeshDimension();
6055 if(spaceDim!=2 && spaceDim!=3)
6056 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6057 if(meshDim!=2 && meshDim!=3)
6058 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6059 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6061 int nbOfCells=getNumberOfCells();
6062 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6063 arr->alloc(nbOfCells,1);
6064 double *pt=arr->getPointer();
6065 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6066 const int *conn=_nodal_connec->getConstPointer();
6067 const int *connI=_nodal_connec_index->getConstPointer();
6068 const double *coo=_coords->getConstPointer();
6070 for(int i=0;i<nbOfCells;i++,pt++)
6072 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6075 case INTERP_KERNEL::NORM_TRI3:
6077 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6078 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6081 case INTERP_KERNEL::NORM_QUAD4:
6083 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6084 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6087 case INTERP_KERNEL::NORM_TETRA4:
6089 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6090 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6094 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6096 conn+=connI[i+1]-connI[i];
6098 ret->setName("AspectRatio");
6099 ret->synchronizeTimeWithSupport();
6104 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6105 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6106 * treated: INTERP_KERNEL::NORM_QUAD4.
6107 * For a cell of other type an exception is thrown.
6108 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6109 * cells and one time, lying on \a this mesh. The caller is to delete this
6110 * field using decrRef() as it is no more needed.
6111 * \throw If the coordinates array is not set.
6112 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6113 * \throw If the connectivity data array has more than one component.
6114 * \throw If the connectivity data array has a named component.
6115 * \throw If the connectivity index data array has more than one component.
6116 * \throw If the connectivity index data array has a named component.
6117 * \throw If \a this->getMeshDimension() != 2.
6118 * \throw If \a this->getSpaceDimension() != 3.
6119 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6121 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6124 int spaceDim=getSpaceDimension();
6125 int meshDim=getMeshDimension();
6127 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6129 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6130 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6132 int nbOfCells=getNumberOfCells();
6133 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6134 arr->alloc(nbOfCells,1);
6135 double *pt=arr->getPointer();
6136 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6137 const int *conn=_nodal_connec->getConstPointer();
6138 const int *connI=_nodal_connec_index->getConstPointer();
6139 const double *coo=_coords->getConstPointer();
6141 for(int i=0;i<nbOfCells;i++,pt++)
6143 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6146 case INTERP_KERNEL::NORM_QUAD4:
6148 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6149 *pt=INTERP_KERNEL::quadWarp(tmp);
6153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6155 conn+=connI[i+1]-connI[i];
6157 ret->setName("Warp");
6158 ret->synchronizeTimeWithSupport();
6164 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6165 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6166 * treated: INTERP_KERNEL::NORM_QUAD4.
6167 * For a cell of other type an exception is thrown.
6168 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6169 * cells and one time, lying on \a this mesh. The caller is to delete this
6170 * field using decrRef() as it is no more needed.
6171 * \throw If the coordinates array is not set.
6172 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6173 * \throw If the connectivity data array has more than one component.
6174 * \throw If the connectivity data array has a named component.
6175 * \throw If the connectivity index data array has more than one component.
6176 * \throw If the connectivity index data array has a named component.
6177 * \throw If \a this->getMeshDimension() != 2.
6178 * \throw If \a this->getSpaceDimension() != 3.
6179 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6181 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6184 int spaceDim=getSpaceDimension();
6185 int meshDim=getMeshDimension();
6187 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6189 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6190 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6192 int nbOfCells=getNumberOfCells();
6193 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6194 arr->alloc(nbOfCells,1);
6195 double *pt=arr->getPointer();
6196 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6197 const int *conn=_nodal_connec->getConstPointer();
6198 const int *connI=_nodal_connec_index->getConstPointer();
6199 const double *coo=_coords->getConstPointer();
6201 for(int i=0;i<nbOfCells;i++,pt++)
6203 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6206 case INTERP_KERNEL::NORM_QUAD4:
6208 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6209 *pt=INTERP_KERNEL::quadSkew(tmp);
6213 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6215 conn+=connI[i+1]-connI[i];
6217 ret->setName("Skew");
6218 ret->synchronizeTimeWithSupport();
6223 * This method aggregate the bbox of each cell and put it into bbox parameter.
6225 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6227 * \throw If \a this is not fully set (coordinates and connectivity).
6228 * \throw If a cell in \a this has no valid nodeId.
6230 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6232 checkFullyDefined();
6233 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6234 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6235 double *bbox(ret->getPointer());
6236 for(int i=0;i<nbOfCells*spaceDim;i++)
6238 bbox[2*i]=std::numeric_limits<double>::max();
6239 bbox[2*i+1]=-std::numeric_limits<double>::max();
6241 const double *coordsPtr(_coords->getConstPointer());
6242 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6243 for(int i=0;i<nbOfCells;i++)
6245 int offset=connI[i]+1;
6246 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6247 for(int j=0;j<nbOfNodesForCell;j++)
6249 int nodeId=conn[offset+j];
6250 if(nodeId>=0 && nodeId<nbOfNodes)
6252 for(int k=0;k<spaceDim;k++)
6254 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6255 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6262 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6263 throw INTERP_KERNEL::Exception(oss.str().c_str());
6271 namespace ParaMEDMEMImpl
6276 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6277 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6286 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6287 bool operator() (const int& pos) { return _conn[pos]==_val; }
6297 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6298 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6299 * \a this is composed in cell types.
6300 * The returned array is of size 3*n where n is the number of different types present in \a this.
6301 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6302 * This parameter is kept only for compatibility with other methode listed above.
6304 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6306 checkConnectivityFullyDefined();
6307 const int *conn=_nodal_connec->getConstPointer();
6308 const int *connI=_nodal_connec_index->getConstPointer();
6309 const int *work=connI;
6310 int nbOfCells=getNumberOfCells();
6311 std::size_t n=getAllGeoTypes().size();
6312 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6313 std::set<INTERP_KERNEL::NormalizedCellType> types;
6314 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6316 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6317 if(types.find(typ)!=types.end())
6319 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6320 oss << " is not contiguous !";
6321 throw INTERP_KERNEL::Exception(oss.str().c_str());
6325 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6326 ret[3*i+1]=(int)std::distance(work,work2);
6333 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6334 * only for types cell, type node is not managed.
6335 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6336 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6337 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6338 * If 2 or more same geometric type is in \a code and exception is thrown too.
6340 * This method firstly checks
6341 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6342 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6343 * an exception is thrown too.
6345 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6346 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6347 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6349 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6353 std::size_t sz=code.size();
6356 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6357 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6359 bool isNoPflUsed=true;
6360 for(std::size_t i=0;i<n;i++)
6361 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6363 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6365 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6366 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6367 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6370 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6373 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6374 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6375 if(types.size()==_types.size())
6378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6380 int *retPtr=ret->getPointer();
6381 const int *connI=_nodal_connec_index->getConstPointer();
6382 const int *conn=_nodal_connec->getConstPointer();
6383 int nbOfCells=getNumberOfCells();
6386 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6388 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6389 int offset=(int)std::distance(connI,i);
6390 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6391 int nbOfCellsOfCurType=(int)std::distance(i,j);
6392 if(code[3*kk+2]==-1)
6393 for(int k=0;k<nbOfCellsOfCurType;k++)
6397 int idInIdsPerType=code[3*kk+2];
6398 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6400 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6403 zePfl->checkAllocated();
6404 if(zePfl->getNumberOfComponents()==1)
6406 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6408 if(*k>=0 && *k<nbOfCellsOfCurType)
6409 *retPtr=(*k)+offset;
6412 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6413 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6414 throw INTERP_KERNEL::Exception(oss.str().c_str());
6419 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6422 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6426 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6427 oss << " should be in [0," << idsPerType.size() << ") !";
6428 throw INTERP_KERNEL::Exception(oss.str().c_str());
6437 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6438 * 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.
6439 * 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.
6440 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6442 * \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.
6443 * \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,
6444 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6445 * \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.
6446 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6447 * \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
6449 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6453 if(profile->getNumberOfComponents()!=1)
6454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6455 checkConnectivityFullyDefined();
6456 const int *conn=_nodal_connec->getConstPointer();
6457 const int *connI=_nodal_connec_index->getConstPointer();
6458 int nbOfCells=getNumberOfCells();
6459 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6460 std::vector<int> typeRangeVals(1);
6461 for(const int *i=connI;i!=connI+nbOfCells;)
6463 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6464 if(std::find(types.begin(),types.end(),curType)!=types.end())
6466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6468 types.push_back(curType);
6469 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6470 typeRangeVals.push_back((int)std::distance(connI,i));
6473 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6474 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6475 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6476 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6479 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6480 code.resize(3*nbOfCastsFinal);
6481 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6482 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6483 for(int i=0;i<nbOfCastsFinal;i++)
6485 int castId=castsPresent->getIJ(i,0);
6486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6487 idsInPflPerType2.push_back(tmp3);
6488 code[3*i]=(int)types[castId];
6489 code[3*i+1]=tmp3->getNumberOfTuples();
6490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6491 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6493 tmp4->copyStringInfoFrom(*profile);
6494 idsPerType2.push_back(tmp4);
6495 code[3*i+2]=(int)idsPerType2.size()-1;
6502 std::size_t sz2=idsInPflPerType2.size();
6503 idsInPflPerType.resize(sz2);
6504 for(std::size_t i=0;i<sz2;i++)
6506 DataArrayInt *locDa=idsInPflPerType2[i];
6508 idsInPflPerType[i]=locDa;
6510 std::size_t sz=idsPerType2.size();
6511 idsPerType.resize(sz);
6512 for(std::size_t i=0;i<sz;i++)
6514 DataArrayInt *locDa=idsPerType2[i];
6516 idsPerType[i]=locDa;
6521 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6522 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6523 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6524 * 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.
6526 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6528 checkFullyDefined();
6529 nM1LevMesh->checkFullyDefined();
6530 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6531 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6532 if(_coords!=nM1LevMesh->getCoords())
6533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6535 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6536 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6538 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6539 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6540 tmp->setConnectivity(tmp0,tmp1);
6541 tmp->renumberCells(ret0->getConstPointer(),false);
6542 revDesc=tmp->getNodalConnectivity();
6543 revDescIndx=tmp->getNodalConnectivityIndex();
6544 DataArrayInt *ret=0;
6545 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6548 ret->getMaxValue(tmp2);
6550 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6551 throw INTERP_KERNEL::Exception(oss.str().c_str());
6556 revDescIndx->incrRef();
6559 meshnM1Old2New=ret0;
6564 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6565 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6566 * in "Old to New" mode.
6567 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6568 * this array using decrRef() as it is no more needed.
6569 * \throw If the nodal connectivity of cells is not defined.
6571 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6573 checkConnectivityFullyDefined();
6574 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6575 renumberCells(ret->getConstPointer(),false);
6580 * This methods checks that cells are sorted by their types.
6581 * This method makes asumption (no check) that connectivity is correctly set before calling.
6583 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6585 checkFullyDefined();
6586 const int *conn=_nodal_connec->getConstPointer();
6587 const int *connI=_nodal_connec_index->getConstPointer();
6588 int nbOfCells=getNumberOfCells();
6589 std::set<INTERP_KERNEL::NormalizedCellType> types;
6590 for(const int *i=connI;i!=connI+nbOfCells;)
6592 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6593 if(types.find(curType)!=types.end())
6595 types.insert(curType);
6596 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6602 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6603 * The geometric type order is specified by MED file.
6605 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6607 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6609 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6613 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6614 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6615 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6616 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6618 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6620 checkFullyDefined();
6621 const int *conn=_nodal_connec->getConstPointer();
6622 const int *connI=_nodal_connec_index->getConstPointer();
6623 int nbOfCells=getNumberOfCells();
6627 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6628 for(const int *i=connI;i!=connI+nbOfCells;)
6630 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6631 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6632 if(isTypeExists!=orderEnd)
6634 int pos=(int)std::distance(orderBg,isTypeExists);
6638 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6642 if(sg.find(curType)==sg.end())
6644 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6655 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6656 * 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
6657 * 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'.
6659 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6661 checkConnectivityFullyDefined();
6662 int nbOfCells=getNumberOfCells();
6663 const int *conn=_nodal_connec->getConstPointer();
6664 const int *connI=_nodal_connec_index->getConstPointer();
6665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6667 tmpa->alloc(nbOfCells,1);
6668 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6669 tmpb->fillWithZero();
6670 int *tmp=tmpa->getPointer();
6671 int *tmp2=tmpb->getPointer();
6672 for(const int *i=connI;i!=connI+nbOfCells;i++)
6674 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6677 int pos=(int)std::distance(orderBg,where);
6679 tmp[std::distance(connI,i)]=pos;
6683 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6684 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6685 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6686 throw INTERP_KERNEL::Exception(oss.str().c_str());
6689 nbPerType=tmpb.retn();
6694 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6696 * \return a new object containing the old to new correspondance.
6698 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6700 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6702 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6706 * 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.
6707 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6708 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6709 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6711 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6713 DataArrayInt *nbPerType=0;
6714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6715 nbPerType->decrRef();
6716 return tmpa->buildPermArrPerLevel();
6720 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6721 * The number of cells remains unchanged after the call of this method.
6722 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6723 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6725 * \return the array giving the correspondance old to new.
6727 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6729 checkFullyDefined();
6731 const int *conn=_nodal_connec->getConstPointer();
6732 const int *connI=_nodal_connec_index->getConstPointer();
6733 int nbOfCells=getNumberOfCells();
6734 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6735 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6736 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6738 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6739 types.push_back(curType);
6740 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6742 DataArrayInt *ret=DataArrayInt::New();
6743 ret->alloc(nbOfCells,1);
6744 int *retPtr=ret->getPointer();
6745 std::fill(retPtr,retPtr+nbOfCells,-1);
6747 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6749 for(const int *i=connI;i!=connI+nbOfCells;i++)
6750 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6751 retPtr[std::distance(connI,i)]=newCellId++;
6753 renumberCells(retPtr,false);
6758 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6759 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6760 * This method makes asumption that connectivity is correctly set before calling.
6762 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6764 checkConnectivityFullyDefined();
6765 const int *conn=_nodal_connec->getConstPointer();
6766 const int *connI=_nodal_connec_index->getConstPointer();
6767 int nbOfCells=getNumberOfCells();
6768 std::vector<MEDCouplingUMesh *> ret;
6769 for(const int *i=connI;i!=connI+nbOfCells;)
6771 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6772 int beginCellId=(int)std::distance(connI,i);
6773 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6774 int endCellId=(int)std::distance(connI,i);
6775 int sz=endCellId-beginCellId;
6776 int *cells=new int[sz];
6777 for(int j=0;j<sz;j++)
6778 cells[j]=beginCellId+j;
6779 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6787 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6788 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6789 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6791 * \return a newly allocated instance, that the caller must manage.
6792 * \throw If \a this contains more than one geometric type.
6793 * \throw If the nodal connectivity of \a this is not fully defined.
6794 * \throw If the internal data is not coherent.
6796 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6798 checkConnectivityFullyDefined();
6799 if(_types.size()!=1)
6800 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6801 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6802 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6803 ret->setCoords(getCoords());
6804 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6808 retC->setNodalConnectivity(c);
6812 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6814 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6815 DataArrayInt *c=0,*ci=0;
6816 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6818 retD->setNodalConnectivity(cs,cis);
6823 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6825 checkConnectivityFullyDefined();
6826 if(_types.size()!=1)
6827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6828 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6829 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6832 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6833 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6834 throw INTERP_KERNEL::Exception(oss.str().c_str());
6836 int nbCells=getNumberOfCells();
6838 int nbNodesPerCell=(int)cm.getNumberOfNodes();
6839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6840 int *outPtr=connOut->getPointer();
6841 const int *conn=_nodal_connec->begin();
6842 const int *connI=_nodal_connec_index->begin();
6844 for(int i=0;i<nbCells;i++,connI++)
6846 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6847 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6850 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 << ") !";
6851 throw INTERP_KERNEL::Exception(oss.str().c_str());
6854 return connOut.retn();
6857 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6859 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6860 checkConnectivityFullyDefined();
6861 if(_types.size()!=1)
6862 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6863 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6865 throw INTERP_KERNEL::Exception(msg0);
6866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6867 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6868 int *cp(c->getPointer()),*cip(ci->getPointer());
6869 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6871 for(int i=0;i<nbCells;i++,cip++,incip++)
6873 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6874 int delta(stop-strt);
6877 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6878 cp=std::copy(incp+strt,incp+stop,cp);
6880 throw INTERP_KERNEL::Exception(msg0);
6883 throw INTERP_KERNEL::Exception(msg0);
6884 cip[1]=cip[0]+delta;
6886 nodalConn=c.retn(); nodalConnIndex=ci.retn();
6890 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6891 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6892 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6893 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6894 * are not used here to avoid the build of big permutation array.
6896 * \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
6897 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6898 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6899 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6900 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6901 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6902 * \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
6903 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6905 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6906 DataArrayInt *&szOfCellGrpOfSameType,
6907 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6909 std::vector<const MEDCouplingUMesh *> ms2;
6910 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6913 (*it)->checkConnectivityFullyDefined();
6917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6918 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6919 int meshDim=ms2[0]->getMeshDimension();
6920 std::vector<const MEDCouplingUMesh *> m1ssm;
6921 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6923 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6924 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6927 ret1->alloc(0,1); ret2->alloc(0,1);
6928 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6930 if(meshDim!=(*it)->getMeshDimension())
6931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6932 if(refCoo!=(*it)->getCoords())
6933 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6934 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6935 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6936 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6937 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6939 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6940 m1ssmSingleAuto.push_back(singleCell);
6941 m1ssmSingle.push_back(singleCell);
6942 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6946 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6947 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6948 for(std::size_t i=0;i<m1ssm.size();i++)
6949 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6950 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6951 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6952 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6957 * This method returns a newly created DataArrayInt instance.
6958 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6960 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6962 checkFullyDefined();
6963 const int *conn=_nodal_connec->getConstPointer();
6964 const int *connIndex=_nodal_connec_index->getConstPointer();
6965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6966 for(const int *w=begin;w!=end;w++)
6967 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6968 ret->pushBackSilent(*w);
6973 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6974 * are in [0:getNumberOfCells())
6976 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6978 checkFullyDefined();
6979 const int *conn=_nodal_connec->getConstPointer();
6980 const int *connI=_nodal_connec_index->getConstPointer();
6981 int nbOfCells=getNumberOfCells();
6982 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6983 int *tmp=new int[nbOfCells];
6984 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6987 for(const int *i=connI;i!=connI+nbOfCells;i++)
6988 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6989 tmp[std::distance(connI,i)]=j++;
6991 DataArrayInt *ret=DataArrayInt::New();
6992 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6993 ret->copyStringInfoFrom(*da);
6994 int *retPtr=ret->getPointer();
6995 const int *daPtr=da->getConstPointer();
6996 int nbOfElems=da->getNbOfElems();
6997 for(int k=0;k<nbOfElems;k++)
6998 retPtr[k]=tmp[daPtr[k]];
7004 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7005 * This method \b works \b for mesh sorted by type.
7006 * cells whose ids is in 'idsPerGeoType' array.
7007 * This method conserves coords and name of mesh.
7009 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7011 std::vector<int> code=getDistributionOfTypes();
7012 std::size_t nOfTypesInThis=code.size()/3;
7013 int sz=0,szOfType=0;
7014 for(std::size_t i=0;i<nOfTypesInThis;i++)
7019 szOfType=code[3*i+1];
7021 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7022 if(*work<0 || *work>=szOfType)
7024 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7025 oss << ". It should be in [0," << szOfType << ") !";
7026 throw INTERP_KERNEL::Exception(oss.str().c_str());
7028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7029 int *idsPtr=idsTokeep->getPointer();
7031 for(std::size_t i=0;i<nOfTypesInThis;i++)
7034 for(int j=0;j<code[3*i+1];j++)
7037 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7038 offset+=code[3*i+1];
7040 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7041 ret->copyTinyInfoFrom(this);
7046 * This method returns a vector of size 'this->getNumberOfCells()'.
7047 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7049 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7051 int ncell=getNumberOfCells();
7052 std::vector<bool> ret(ncell);
7053 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7054 const int *c=getNodalConnectivity()->getConstPointer();
7055 for(int i=0;i<ncell;i++)
7057 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7058 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7059 ret[i]=cm.isQuadratic();
7065 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7067 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7069 if(other->getType()!=UNSTRUCTURED)
7070 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7071 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7072 return MergeUMeshes(this,otherC);
7076 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7077 * computed by averaging coordinates of cell nodes, so this method is not a right
7078 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7079 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7080 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7081 * components. The caller is to delete this array using decrRef() as it is
7083 * \throw If the coordinates array is not set.
7084 * \throw If the nodal connectivity of cells is not defined.
7085 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7087 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7089 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7090 int spaceDim=getSpaceDimension();
7091 int nbOfCells=getNumberOfCells();
7092 ret->alloc(nbOfCells,spaceDim);
7093 ret->copyStringInfoFrom(*getCoords());
7094 double *ptToFill=ret->getPointer();
7095 const int *nodal=_nodal_connec->getConstPointer();
7096 const int *nodalI=_nodal_connec_index->getConstPointer();
7097 const double *coor=_coords->getConstPointer();
7098 for(int i=0;i<nbOfCells;i++)
7100 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7101 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7108 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7109 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7111 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7112 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7114 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7115 * \throw If \a this is not fully defined (coordinates and connectivity)
7116 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7118 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7120 checkFullyDefined();
7121 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7122 int spaceDim=getSpaceDimension();
7123 int nbOfCells=getNumberOfCells();
7124 int nbOfNodes=getNumberOfNodes();
7125 ret->alloc(nbOfCells,spaceDim);
7126 double *ptToFill=ret->getPointer();
7127 const int *nodal=_nodal_connec->getConstPointer();
7128 const int *nodalI=_nodal_connec_index->getConstPointer();
7129 const double *coor=_coords->getConstPointer();
7130 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7132 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7133 std::fill(ptToFill,ptToFill+spaceDim,0.);
7134 if(type!=INTERP_KERNEL::NORM_POLYHED)
7136 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7138 if(*conn>=0 && *conn<nbOfNodes)
7139 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7142 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7143 throw INTERP_KERNEL::Exception(oss.str().c_str());
7146 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7147 if(nbOfNodesInCell>0)
7148 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7151 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7152 throw INTERP_KERNEL::Exception(oss.str().c_str());
7157 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7159 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7161 if(*it>=0 && *it<nbOfNodes)
7162 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7165 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7166 throw INTERP_KERNEL::Exception(oss.str().c_str());
7170 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7173 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7174 throw INTERP_KERNEL::Exception(oss.str().c_str());
7182 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7183 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7184 * are specified via an array of cell ids.
7185 * \warning Validity of the specified cell ids is not checked!
7186 * Valid range is [ 0, \a this->getNumberOfCells() ).
7187 * \param [in] begin - an array of cell ids of interest.
7188 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7189 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7190 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7191 * caller is to delete this array using decrRef() as it is no more needed.
7192 * \throw If the coordinates array is not set.
7193 * \throw If the nodal connectivity of cells is not defined.
7195 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7196 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7198 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7200 DataArrayDouble *ret=DataArrayDouble::New();
7201 int spaceDim=getSpaceDimension();
7202 int nbOfTuple=(int)std::distance(begin,end);
7203 ret->alloc(nbOfTuple,spaceDim);
7204 double *ptToFill=ret->getPointer();
7205 double *tmp=new double[spaceDim];
7206 const int *nodal=_nodal_connec->getConstPointer();
7207 const int *nodalI=_nodal_connec_index->getConstPointer();
7208 const double *coor=_coords->getConstPointer();
7209 for(const int *w=begin;w!=end;w++)
7211 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7212 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7220 * 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".
7221 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7222 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7223 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7224 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7226 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7227 * \throw If spaceDim!=3 or meshDim!=2.
7228 * \throw If connectivity of \a this is invalid.
7229 * \throw If connectivity of a cell in \a this points to an invalid node.
7231 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7233 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7234 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7235 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7236 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7237 ret->alloc(nbOfCells,4);
7238 double *retPtr(ret->getPointer());
7239 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7240 const double *coor(_coords->begin());
7241 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7243 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7244 if(nodalI[1]-nodalI[0]>=3)
7246 for(int j=0;j<3;j++)
7248 int nodeId(nodal[nodalI[0]+1+j]);
7249 if(nodeId>=0 && nodeId<nbOfNodes)
7250 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7253 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7254 throw INTERP_KERNEL::Exception(oss.str().c_str());
7260 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7261 throw INTERP_KERNEL::Exception(oss.str().c_str());
7263 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7264 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7270 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7273 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7277 da->checkAllocated();
7278 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7280 int nbOfTuples=da->getNumberOfTuples();
7281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7283 c->alloc(2*nbOfTuples,1);
7284 cI->alloc(nbOfTuples+1,1);
7285 int *cp=c->getPointer();
7286 int *cip=cI->getPointer();
7288 for(int i=0;i<nbOfTuples;i++)
7290 *cp++=INTERP_KERNEL::NORM_POINT1;
7294 ret->setConnectivity(c,cI,true);
7298 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7299 * Cells and nodes of
7300 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7301 * \param [in] mesh1 - the first mesh.
7302 * \param [in] mesh2 - the second mesh.
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 mesh1 == NULL or \a mesh2 == NULL.
7307 * \throw If the coordinates array is not set in none of the meshes.
7308 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7309 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7311 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7313 std::vector<const MEDCouplingUMesh *> tmp(2);
7314 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7315 return MergeUMeshes(tmp);
7319 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7320 * Cells and nodes of
7321 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7322 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7323 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7324 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7325 * is no more needed.
7326 * \throw If \a a.size() == 0.
7327 * \throw If \a a[ *i* ] == NULL.
7328 * \throw If the coordinates array is not set in none of the meshes.
7329 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7330 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7332 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7334 std::size_t sz=a.size();
7336 return MergeUMeshesLL(a);
7337 for(std::size_t ii=0;ii<sz;ii++)
7340 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7341 throw INTERP_KERNEL::Exception(oss.str().c_str());
7343 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7344 std::vector< const MEDCouplingUMesh * > aa(sz);
7346 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7348 const MEDCouplingUMesh *cur=a[i];
7349 const DataArrayDouble *coo=cur->getCoords();
7351 spaceDim=coo->getNumberOfComponents();
7354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7355 for(std::size_t i=0;i<sz;i++)
7357 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7360 return MergeUMeshesLL(aa);
7365 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7369 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7370 int meshDim=(*it)->getMeshDimension();
7371 int nbOfCells=(*it)->getNumberOfCells();
7372 int meshLgth=(*it++)->getMeshLength();
7373 for(;it!=a.end();it++)
7375 if(meshDim!=(*it)->getMeshDimension())
7376 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7377 nbOfCells+=(*it)->getNumberOfCells();
7378 meshLgth+=(*it)->getMeshLength();
7380 std::vector<const MEDCouplingPointSet *> aps(a.size());
7381 std::copy(a.begin(),a.end(),aps.begin());
7382 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7383 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7384 ret->setCoords(pts);
7385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7386 c->alloc(meshLgth,1);
7387 int *cPtr=c->getPointer();
7388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7389 cI->alloc(nbOfCells+1,1);
7390 int *cIPtr=cI->getPointer();
7394 for(it=a.begin();it!=a.end();it++)
7396 int curNbOfCell=(*it)->getNumberOfCells();
7397 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7398 const int *curC=(*it)->_nodal_connec->getConstPointer();
7399 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7400 for(int j=0;j<curNbOfCell;j++)
7402 const int *src=curC+curCI[j];
7404 for(;src!=curC+curCI[j+1];src++,cPtr++)
7412 offset+=curCI[curNbOfCell];
7413 offset2+=(*it)->getNumberOfNodes();
7416 ret->setConnectivity(c,cI,true);
7423 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7424 * dimension and sharing the node coordinates array.
7425 * All cells of the first mesh precede all cells of the second mesh
7426 * within the result mesh.
7427 * \param [in] mesh1 - the first mesh.
7428 * \param [in] mesh2 - the second mesh.
7429 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7430 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7431 * is no more needed.
7432 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7433 * \throw If the meshes do not share the node coordinates array.
7434 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7435 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7437 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7439 std::vector<const MEDCouplingUMesh *> tmp(2);
7440 tmp[0]=mesh1; tmp[1]=mesh2;
7441 return MergeUMeshesOnSameCoords(tmp);
7445 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7446 * dimension and sharing the node coordinates array.
7447 * All cells of the *i*-th mesh precede all cells of the
7448 * (*i*+1)-th mesh within the result mesh.
7449 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7450 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7451 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7452 * is no more needed.
7453 * \throw If \a a.size() == 0.
7454 * \throw If \a a[ *i* ] == NULL.
7455 * \throw If the meshes do not share the node coordinates array.
7456 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7457 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7459 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7462 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7463 for(std::size_t ii=0;ii<meshes.size();ii++)
7466 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7467 throw INTERP_KERNEL::Exception(oss.str().c_str());
7469 const DataArrayDouble *coords=meshes.front()->getCoords();
7470 int meshDim=meshes.front()->getMeshDimension();
7471 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7473 int meshIndexLgth=0;
7474 for(;iter!=meshes.end();iter++)
7476 if(coords!=(*iter)->getCoords())
7477 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7478 if(meshDim!=(*iter)->getMeshDimension())
7479 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7480 meshLgth+=(*iter)->getMeshLength();
7481 meshIndexLgth+=(*iter)->getNumberOfCells();
7483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7484 nodal->alloc(meshLgth,1);
7485 int *nodalPtr=nodal->getPointer();
7486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7487 nodalIndex->alloc(meshIndexLgth+1,1);
7488 int *nodalIndexPtr=nodalIndex->getPointer();
7490 for(iter=meshes.begin();iter!=meshes.end();iter++)
7492 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7493 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7494 int nbOfCells=(*iter)->getNumberOfCells();
7495 int meshLgth2=(*iter)->getMeshLength();
7496 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7497 if(iter!=meshes.begin())
7498 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7500 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7503 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7504 ret->setName("merge");
7505 ret->setMeshDimension(meshDim);
7506 ret->setConnectivity(nodal,nodalIndex,true);
7507 ret->setCoords(coords);
7512 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7513 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7514 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7515 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7516 * New" mode are returned for each input mesh.
7517 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7518 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7519 * valid values [0,1,2], see zipConnectivityTraducer().
7520 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7521 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7522 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7524 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7525 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7526 * is no more needed.
7527 * \throw If \a meshes.size() == 0.
7528 * \throw If \a meshes[ *i* ] == NULL.
7529 * \throw If the meshes do not share the node coordinates array.
7530 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7531 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7532 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7533 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7535 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7537 //All checks are delegated to MergeUMeshesOnSameCoords
7538 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7540 corr.resize(meshes.size());
7541 std::size_t nbOfMeshes=meshes.size();
7543 const int *o2nPtr=o2n->getConstPointer();
7544 for(std::size_t i=0;i<nbOfMeshes;i++)
7546 DataArrayInt *tmp=DataArrayInt::New();
7547 int curNbOfCells=meshes[i]->getNumberOfCells();
7548 tmp->alloc(curNbOfCells,1);
7549 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7550 offset+=curNbOfCells;
7551 tmp->setName(meshes[i]->getName().c_str());
7558 * Makes all given meshes share the nodal connectivity array. The common connectivity
7559 * array is created by concatenating the connectivity arrays of all given meshes. All
7560 * the given meshes must be of the same space dimension but dimension of cells **can
7561 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7562 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7563 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7564 * \param [in,out] meshes - a vector of meshes to update.
7565 * \throw If any of \a meshes is NULL.
7566 * \throw If the coordinates array is not set in any of \a meshes.
7567 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7568 * \throw If \a meshes are of different space dimension.
7570 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7572 std::size_t sz=meshes.size();
7575 std::vector< const DataArrayDouble * > coords(meshes.size());
7576 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7577 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7581 (*it)->checkConnectivityFullyDefined();
7582 const DataArrayDouble *coo=(*it)->getCoords();
7587 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7588 oss << " has no coordinate array defined !";
7589 throw INTERP_KERNEL::Exception(oss.str().c_str());
7594 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7595 oss << " is null !";
7596 throw INTERP_KERNEL::Exception(oss.str().c_str());
7599 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7600 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7601 int offset=(*it)->getNumberOfNodes();
7602 (*it++)->setCoords(res);
7603 for(;it!=meshes.end();it++)
7605 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7606 (*it)->setCoords(res);
7607 (*it)->shiftNodeNumbersInConn(offset);
7608 offset+=oldNumberOfNodes;
7613 * Merges nodes coincident with a given precision within all given meshes that share
7614 * the nodal connectivity array. The given meshes **can be of different** mesh
7615 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7616 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7617 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7618 * \param [in,out] meshes - a vector of meshes to update.
7619 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7620 * \throw If any of \a meshes is NULL.
7621 * \throw If the \a meshes do not share the same node coordinates array.
7622 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7624 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7628 std::set<const DataArrayDouble *> s;
7629 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7632 s.insert((*it)->getCoords());
7635 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 !";
7636 throw INTERP_KERNEL::Exception(oss.str().c_str());
7641 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 !";
7642 throw INTERP_KERNEL::Exception(oss.str().c_str());
7644 const DataArrayDouble *coo=*(s.begin());
7648 DataArrayInt *comm,*commI;
7649 coo->findCommonTuples(eps,-1,comm,commI);
7650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7651 int oldNbOfNodes=coo->getNumberOfTuples();
7653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7654 if(oldNbOfNodes==newNbOfNodes)
7656 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7657 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7659 (*it)->renumberNodesInConn(o2n->getConstPointer());
7660 (*it)->setCoords(newCoords);
7665 * 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.
7666 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7667 * \param isQuad specifies the policy of connectivity.
7668 * @ret in/out parameter in which the result will be append
7670 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7672 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7673 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7674 ret.push_back(cm.getExtrudedType());
7675 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7678 case INTERP_KERNEL::NORM_POINT1:
7680 ret.push_back(connBg[1]);
7681 ret.push_back(connBg[1]+nbOfNodesPerLev);
7684 case INTERP_KERNEL::NORM_SEG2:
7686 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7687 ret.insert(ret.end(),conn,conn+4);
7690 case INTERP_KERNEL::NORM_SEG3:
7692 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7693 ret.insert(ret.end(),conn,conn+8);
7696 case INTERP_KERNEL::NORM_QUAD4:
7698 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7699 ret.insert(ret.end(),conn,conn+8);
7702 case INTERP_KERNEL::NORM_TRI3:
7704 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7705 ret.insert(ret.end(),conn,conn+6);
7708 case INTERP_KERNEL::NORM_TRI6:
7710 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,
7711 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7712 ret.insert(ret.end(),conn,conn+15);
7715 case INTERP_KERNEL::NORM_QUAD8:
7718 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7719 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7720 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7722 ret.insert(ret.end(),conn,conn+20);
7725 case INTERP_KERNEL::NORM_POLYGON:
7727 std::back_insert_iterator< std::vector<int> > ii(ret);
7728 std::copy(connBg+1,connEnd,ii);
7730 std::reverse_iterator<const int *> rConnBg(connEnd);
7731 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7732 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7733 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7734 for(std::size_t i=0;i<nbOfRadFaces;i++)
7737 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7738 std::copy(conn,conn+4,ii);
7743 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7748 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7750 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7752 double v[3]={0.,0.,0.};
7753 std::size_t sz=std::distance(begin,end);
7756 for(std::size_t i=0;i<sz;i++)
7758 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];
7759 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7760 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7762 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7766 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7768 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7770 std::vector<std::pair<int,int> > edges;
7771 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7772 const int *bgFace=begin;
7773 for(std::size_t i=0;i<nbOfFaces;i++)
7775 const int *endFace=std::find(bgFace+1,end,-1);
7776 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7777 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7779 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7780 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7782 edges.push_back(p1);
7786 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7790 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7792 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7794 double vec0[3],vec1[3];
7795 std::size_t sz=std::distance(begin,end);
7797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7798 int nbOfNodes=(int)sz/2;
7799 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7800 const double *pt0=coords+3*begin[0];
7801 const double *pt1=coords+3*begin[nbOfNodes];
7802 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7803 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7806 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7808 std::size_t sz=std::distance(begin,end);
7809 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7810 std::size_t nbOfNodes(sz/2);
7811 std::copy(begin,end,(int *)tmp);
7812 for(std::size_t j=1;j<nbOfNodes;j++)
7814 begin[j]=tmp[nbOfNodes-j];
7815 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7819 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7821 std::size_t sz=std::distance(begin,end);
7823 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7824 double vec0[3],vec1[3];
7825 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7826 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];
7827 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;
7830 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7832 std::size_t sz=std::distance(begin,end);
7834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7836 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7837 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7838 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7842 * 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 )
7843 * 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
7846 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7847 * \param [in] coords the coordinates with nb of components exactly equal to 3
7848 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7849 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7850 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7852 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
7854 int nbFaces=std::count(begin+1,end,-1)+1;
7855 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7856 double *vPtr=v->getPointer();
7857 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7858 double *pPtr=p->getPointer();
7859 const int *stFaceConn=begin+1;
7860 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7862 const int *endFaceConn=std::find(stFaceConn,end,-1);
7863 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7864 stFaceConn=endFaceConn+1;
7866 pPtr=p->getPointer(); vPtr=v->getPointer();
7867 DataArrayInt *comm1=0,*commI1=0;
7868 v->findCommonTuples(eps,-1,comm1,commI1);
7869 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7870 const int *comm1Ptr=comm1->getConstPointer();
7871 const int *commI1Ptr=commI1->getConstPointer();
7872 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7873 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7875 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7876 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7877 mm->finishInsertingCells();
7879 for(int i=0;i<nbOfGrps1;i++)
7881 int vecId=comm1Ptr[commI1Ptr[i]];
7882 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7883 DataArrayInt *comm2=0,*commI2=0;
7884 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7886 const int *comm2Ptr=comm2->getConstPointer();
7887 const int *commI2Ptr=commI2->getConstPointer();
7888 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7889 for(int j=0;j<nbOfGrps2;j++)
7891 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7893 res->insertAtTheEnd(begin,end);
7894 res->pushBackSilent(-1);
7898 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7900 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7901 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7902 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7903 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7906 const int *idsNodePtr=idsNode->getConstPointer();
7907 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];
7908 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7909 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7910 if(std::abs(norm)>eps)
7912 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7913 mm3->rotate(center,vec,angle);
7915 mm3->changeSpaceDimension(2);
7916 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7917 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7918 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7919 int nbOfCells=mm4->getNumberOfCells();
7920 for(int k=0;k<nbOfCells;k++)
7923 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7924 res->pushBackSilent(idsNodePtr[*work]);
7925 res->pushBackSilent(-1);
7930 res->popBackSilent();
7934 * 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
7935 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7937 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7938 * \param [in] coords coordinates expected to have 3 components.
7939 * \param [in] begin start of the nodal connectivity of the face.
7940 * \param [in] end end of the nodal connectivity (excluded) of the face.
7941 * \param [out] v the normalized vector of size 3
7942 * \param [out] p the pos of plane
7944 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7946 std::size_t nbPoints=std::distance(begin,end);
7948 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7949 double vec[3]={0.,0.,0.};
7951 bool refFound=false;
7952 for(;j<nbPoints-1 && !refFound;j++)
7954 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7955 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7956 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7957 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7961 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7964 for(std::size_t i=j;i<nbPoints-1;i++)
7967 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7968 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7969 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7970 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7973 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7974 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];
7975 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7978 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7979 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7983 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7987 * This method tries to obtain a well oriented polyhedron.
7988 * If the algorithm fails, an exception will be thrown.
7990 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7992 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7993 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7994 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7996 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7997 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7998 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8000 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8003 std::size_t smthChanged=0;
8004 for(std::size_t i=0;i<nbOfFaces;i++)
8006 endFace=std::find(bgFace+1,end,-1);
8007 nbOfEdgesInFace=std::distance(bgFace,endFace);
8011 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8013 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8014 std::pair<int,int> p2(p1.second,p1.first);
8015 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8016 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8017 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8022 std::reverse(bgFace+1,endFace);
8023 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8025 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8026 std::pair<int,int> p2(p1.second,p1.first);
8027 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8028 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8029 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8030 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8031 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8032 if(it!=edgesOK.end())
8035 edgesFinished.push_back(p1);
8038 edgesOK.push_back(p1);
8045 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8047 if(!edgesOK.empty())
8048 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8049 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8050 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8052 for(std::size_t i=0;i<nbOfFaces;i++)
8054 endFace=std::find(bgFace+1,end,-1);
8055 std::reverse(bgFace+1,endFace);
8062 * This method makes the assumption spacedimension == meshdimension == 2.
8063 * This method works only for linear cells.
8065 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8067 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8069 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8070 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8071 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8073 int nbOfNodesExpected=m->getNumberOfNodes();
8074 if(m->getNumberOfCells()!=nbOfNodesExpected)
8075 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8077 const int *n2oPtr=n2o->getConstPointer();
8078 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8079 m->getReverseNodalConnectivity(revNodal,revNodalI);
8080 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8081 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8082 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8084 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
8085 if(nbOfNodesExpected<1)
8088 int prevNode=nodalPtr[nodalIPtr[0]+1];
8089 *work++=n2oPtr[prevNode];
8090 for(int i=1;i<nbOfNodesExpected;i++)
8092 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8094 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8095 conn.erase(prevNode);
8098 int curNode=*(conn.begin());
8099 *work++=n2oPtr[curNode];
8100 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8101 shar.erase(prevCell);
8104 prevCell=*(shar.begin());
8108 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8120 * This method makes the assumption spacedimension == meshdimension == 3.
8121 * This method works only for linear cells.
8123 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8125 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8127 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8128 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8129 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8130 const int *conn=m->getNodalConnectivity()->getConstPointer();
8131 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8132 int nbOfCells=m->getNumberOfCells();
8133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8134 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8137 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8138 for(int i=1;i<nbOfCells;i++)
8141 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8147 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8148 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8150 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8154 for(int i=0;i<nbOfNodesInCell;i++)
8155 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8156 else if(spaceDim==2)
8158 for(int i=0;i<nbOfNodesInCell;i++)
8160 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8165 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8168 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8170 int nbOfCells=getNumberOfCells();
8172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8173 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,36,4};
8174 ofs << " <" << getVTKDataSetType() << ">\n";
8175 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8176 ofs << " <PointData>\n" << pointData << std::endl;
8177 ofs << " </PointData>\n";
8178 ofs << " <CellData>\n" << cellData << std::endl;
8179 ofs << " </CellData>\n";
8180 ofs << " <Points>\n";
8181 if(getSpaceDimension()==3)
8182 _coords->writeVTK(ofs,8,"Points",byteData);
8185 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8186 coo->writeVTK(ofs,8,"Points",byteData);
8188 ofs << " </Points>\n";
8189 ofs << " <Cells>\n";
8190 const int *cPtr=_nodal_connec->getConstPointer();
8191 const int *cIPtr=_nodal_connec_index->getConstPointer();
8192 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8193 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8195 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8196 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8197 int szFaceOffsets=0,szConn=0;
8198 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8201 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8204 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8205 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8209 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8210 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8211 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8212 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8213 w4=std::copy(c.begin(),c.end(),w4);
8216 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8217 types->writeVTK(ofs,8,"UInt8","types",byteData);
8218 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8219 if(szFaceOffsets!=0)
8220 {//presence of Polyhedra
8221 connectivity->reAlloc(szConn);
8222 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8223 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8224 w1=faces->getPointer();
8225 for(int i=0;i<nbOfCells;i++)
8226 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8228 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8230 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8231 for(int j=0;j<nbFaces;j++)
8233 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8234 *w1++=(int)std::distance(w6,w5);
8235 w1=std::copy(w6,w5,w1);
8239 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8241 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8242 ofs << " </Cells>\n";
8243 ofs << " </Piece>\n";
8244 ofs << " </" << getVTKDataSetType() << ">\n";
8247 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8249 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8251 { stream << " Not set !"; return ; }
8252 stream << " Mesh dimension : " << _mesh_dim << ".";
8256 { stream << " No coordinates set !"; return ; }
8257 if(!_coords->isAllocated())
8258 { stream << " Coordinates set but not allocated !"; return ; }
8259 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8260 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8261 if(!_nodal_connec_index)
8262 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8263 if(!_nodal_connec_index->isAllocated())
8264 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8265 int lgth=_nodal_connec_index->getNumberOfTuples();
8266 int cpt=_nodal_connec_index->getNumberOfComponents();
8267 if(cpt!=1 || lgth<1)
8269 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8272 std::string MEDCouplingUMesh::getVTKDataSetType() const
8274 return std::string("UnstructuredGrid");
8278 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8279 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8280 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8282 * \param [in] m1 - the first input mesh which is a partitioned object.
8283 * \param [in] m2 - the second input mesh which is a partition tool.
8284 * \param [in] eps - precision used to detect coincident mesh entities.
8285 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8286 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8287 * this array using decrRef() as it is no more needed.
8288 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8289 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8290 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8291 * any cell of \a m2. The caller is to delete this array using decrRef() as
8292 * it is no more needed.
8293 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8294 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8295 * is no more needed.
8296 * \throw If the coordinates array is not set in any of the meshes.
8297 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8298 * \throw If any of the meshes is not a 2D mesh in 2D space.
8300 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8302 m1->checkFullyDefined();
8303 m2->checkFullyDefined();
8304 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8305 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8306 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8307 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8308 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8309 std::vector<double> addCoo,addCoordsQuadratic;
8310 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8311 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8312 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8313 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8314 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8315 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8316 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8317 std::vector< std::vector<int> > intersectEdge2;
8318 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8319 subDiv2.clear(); dd5=0; dd6=0;
8320 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8321 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8322 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8323 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8325 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8326 addCooDa->alloc((int)(addCoo.size())/2,2);
8327 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8328 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8329 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8330 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8331 std::vector<const DataArrayDouble *> coordss(4);
8332 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8333 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8334 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8339 ret->setConnectivity(conn,connI,true);
8340 ret->setCoords(coo);
8341 cellNb1=c1.retn(); cellNb2=c2.retn();
8345 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8346 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8347 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8348 const std::vector<double>& addCoords,
8349 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8351 static const int SPACEDIM=2;
8352 const double *coo1=m1->getCoords()->getConstPointer();
8353 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8354 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8355 int offset1=m1->getNumberOfNodes();
8356 const double *coo2=m2->getCoords()->getConstPointer();
8357 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8358 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8359 int offset2=offset1+m2->getNumberOfNodes();
8360 int offset3=offset2+((int)addCoords.size())/2;
8361 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8362 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8363 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8364 int ncell1=m1->getNumberOfCells();
8366 for(int i=0;i<ncell1;i++)
8368 std::vector<int> candidates2;
8369 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8370 std::map<INTERP_KERNEL::Node *,int> mapp;
8371 std::map<int,INTERP_KERNEL::Node *> mappRev;
8372 INTERP_KERNEL::QuadraticPolygon pol1;
8373 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8374 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8375 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8376 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8377 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8379 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
8380 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8381 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8382 for(it1.first();!it1.finished();it1.next())
8383 edges1.insert(it1.current()->getPtr());
8385 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8386 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8388 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8390 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8391 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8392 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8393 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8394 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8397 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8399 pol1.initLocationsWithOther(pol2s[ii]);
8400 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8401 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8402 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8408 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8410 catch(INTERP_KERNEL::Exception& e)
8412 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();
8413 throw INTERP_KERNEL::Exception(oss.str().c_str());
8416 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8417 (*it).second->decrRef();
8422 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8425 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8426 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8427 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8428 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8429 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8431 static const int SPACEDIM=2;
8432 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8433 desc2=DataArrayInt::New();
8434 descIndx2=DataArrayInt::New();
8435 revDesc2=DataArrayInt::New();
8436 revDescIndx2=DataArrayInt::New();
8437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8438 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8439 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8440 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8441 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8442 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8443 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8444 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8445 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8446 int ncell1=m1Desc->getNumberOfCells();
8447 int ncell2=m2Desc->getNumberOfCells();
8448 intersectEdge1.resize(ncell1);
8449 colinear2.resize(ncell2);
8450 subDiv2.resize(ncell2);
8451 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8452 std::vector<int> candidates1(1);
8453 int offset1=m1->getNumberOfNodes();
8454 int offset2=offset1+m2->getNumberOfNodes();
8455 for(int i=0;i<ncell1;i++)
8457 std::vector<int> candidates2;
8458 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8459 if(!candidates2.empty())
8461 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8462 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8464 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8465 // this following part is to avoid that a some remove nodes (for example due to a merge between pol1 and pol2) can be replaced by a newlt created one
8466 // This trick garanties that Node * are discriminant
8467 std::set<INTERP_KERNEL::Node *> nodes;
8468 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8469 std::size_t szz(nodes.size());
8470 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8471 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8472 for(std::size_t iii=0;iii<szz;iii++,itt++)
8473 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8474 // end of protection
8475 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8480 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8482 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8483 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8487 * This method performs the 2nd step of Partition of 2D mesh.
8488 * This method has 4 inputs :
8489 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8490 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8491 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8492 * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8493 * \param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8494 * \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.
8495 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8497 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
8499 int offset1=m1->getNumberOfNodes();
8500 int ncell=m2->getNumberOfCells();
8501 const int *c=m2->getNodalConnectivity()->getConstPointer();
8502 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8503 const double *coo=m2->getCoords()->getConstPointer();
8504 const double *cooBis=m1->getCoords()->getConstPointer();
8505 int offset2=offset1+m2->getNumberOfNodes();
8506 intersectEdge.resize(ncell);
8507 for(int i=0;i<ncell;i++,cI++)
8509 const std::vector<int>& divs=subDiv[i];
8510 int nnode=cI[1]-cI[0]-1;
8511 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8512 std::map<INTERP_KERNEL::Node *, int> mapp22;
8513 for(int j=0;j<nnode;j++)
8515 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8516 int nnid=c[(*cI)+j+1];
8517 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8518 mapp22[nn]=nnid+offset1;
8520 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8521 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8522 ((*it).second.first)->decrRef();
8523 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8524 std::map<INTERP_KERNEL::Node *,int> mapp3;
8525 for(std::size_t j=0;j<divs.size();j++)
8528 INTERP_KERNEL::Node *tmp=0;
8530 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8532 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8534 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8538 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8539 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8546 * 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).
8547 * 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
8548 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8549 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8550 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8551 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8552 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8553 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8554 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8555 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8556 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8557 * \param [out] cut3DSuf input/output param.
8559 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8560 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8561 const int *desc, const int *descIndx,
8562 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8564 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8565 int nbOf3DSurfCell=(int)cut3DSurf.size();
8566 for(int i=0;i<nbOf3DSurfCell;i++)
8568 std::vector<int> res;
8569 int offset=descIndx[i];
8570 int nbOfSeg=descIndx[i+1]-offset;
8571 for(int j=0;j<nbOfSeg;j++)
8573 int edgeId=desc[offset+j];
8574 int status=cut3DCurve[edgeId];
8578 res.push_back(status);
8581 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8582 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8590 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8596 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8597 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8600 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8604 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8609 {// case when plane is on a multi colinear edge of a polyhedron
8610 if((int)res.size()==2*nbOfSeg)
8612 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8622 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8623 * 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).
8624 * 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
8625 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8626 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8627 * \param desc is the descending connectivity 3D->3DSurf
8628 * \param descIndx is the descending connectivity index 3D->3DSurf
8630 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8631 const int *desc, const int *descIndx,
8632 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8634 checkFullyDefined();
8635 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8636 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8637 const int *nodal3D=_nodal_connec->getConstPointer();
8638 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8639 int nbOfCells=getNumberOfCells();
8640 for(int i=0;i<nbOfCells;i++)
8642 std::map<int, std::set<int> > m;
8643 int offset=descIndx[i];
8644 int nbOfFaces=descIndx[i+1]-offset;
8647 for(int j=0;j<nbOfFaces;j++)
8649 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8650 if(p.first!=-1 && p.second!=-1)
8654 start=p.first; end=p.second;
8655 m[p.first].insert(p.second);
8656 m[p.second].insert(p.first);
8660 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8661 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8662 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8663 INTERP_KERNEL::NormalizedCellType cmsId;
8664 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8665 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8666 for(unsigned k=0;k<nbOfNodesSon;k++)
8668 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8669 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8676 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8680 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8681 const std::set<int>& s=(*it).second;
8682 std::set<int> s2; s2.insert(prev);
8684 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8687 int val=*s3.begin();
8688 conn.push_back(start);
8695 conn.push_back(end);
8698 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8699 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8700 cellIds->pushBackSilent(i);
8706 * 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
8707 * 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
8708 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8709 * 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
8710 * 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.
8712 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8714 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
8716 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8719 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8720 if(cm.getDimension()==2)
8722 const int *node=nodalConnBg+1;
8723 int startNode=*node++;
8724 double refX=coords[2*startNode];
8725 for(;node!=nodalConnEnd;node++)
8727 if(coords[2*(*node)]<refX)
8730 refX=coords[2*startNode];
8733 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8737 double angle0=-M_PI/2;
8742 double angleNext=0.;
8743 while(nextNode!=startNode)
8747 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8749 if(*node!=tmpOut.back() && *node!=prevNode)
8751 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8752 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8757 res=angle0-angleM+2.*M_PI;
8766 if(nextNode!=startNode)
8768 angle0=angleNext-M_PI;
8771 prevNode=tmpOut.back();
8772 tmpOut.push_back(nextNode);
8775 std::vector<int> tmp3(2*(sz-1));
8776 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8777 std::copy(nodalConnBg+1,nodalConnEnd,it);
8778 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8780 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8783 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8785 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8790 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8791 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8796 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8799 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8803 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8804 * 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.
8806 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8807 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8808 * \param [in,out] arr array in which the remove operation will be done.
8809 * \param [in,out] arrIndx array in the remove operation will modify
8810 * \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])
8811 * \return true if \b arr and \b arrIndx have been modified, false if not.
8813 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
8815 if(!arrIndx || !arr)
8816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8817 if(offsetForRemoval<0)
8818 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8819 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8820 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8821 int *arrIPtr=arrIndx->getPointer();
8824 const int *arrPtr=arr->getConstPointer();
8825 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8826 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8828 if(*arrIPtr-previousArrI>offsetForRemoval)
8830 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8832 if(s.find(*work)==s.end())
8833 arrOut.push_back(*work);
8836 previousArrI=*arrIPtr;
8837 *arrIPtr=(int)arrOut.size();
8839 if(arr->getNumberOfTuples()==(int)arrOut.size())
8841 arr->alloc((int)arrOut.size(),1);
8842 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8847 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8848 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8849 * The selection of extraction is done standardly in new2old format.
8850 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8852 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8853 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8854 * \param [in] arrIn arr origin array from which the extraction will be done.
8855 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8856 * \param [out] arrOut the resulting array
8857 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8858 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8860 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8861 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8863 if(!arrIn || !arrIndxIn)
8864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8865 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8866 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8867 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8868 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8869 const int *arrInPtr=arrIn->getConstPointer();
8870 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8871 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8874 int maxSizeOfArr=arrIn->getNumberOfTuples();
8875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8877 arrIo->alloc((int)(sz+1),1);
8878 const int *idsIt=idsOfSelectBg;
8879 int *work=arrIo->getPointer();
8882 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8884 if(*idsIt>=0 && *idsIt<nbOfGrps)
8885 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8888 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8889 throw INTERP_KERNEL::Exception(oss.str().c_str());
8895 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8896 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8897 throw INTERP_KERNEL::Exception(oss.str().c_str());
8900 arro->alloc(lgth,1);
8901 work=arro->getPointer();
8902 idsIt=idsOfSelectBg;
8903 for(std::size_t i=0;i<sz;i++,idsIt++)
8905 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8906 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8909 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8910 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8911 throw INTERP_KERNEL::Exception(oss.str().c_str());
8915 arrIndexOut=arrIo.retn();
8919 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8920 * 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 ).
8921 * The selection of extraction is done standardly in new2old format.
8922 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8924 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8925 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8926 * \param [in] arrIn arr origin array from which the extraction will be done.
8927 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8928 * \param [out] arrOut the resulting array
8929 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8930 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8932 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8933 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8935 if(!arrIn || !arrIndxIn)
8936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8937 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8938 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8940 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8941 const int *arrInPtr=arrIn->getConstPointer();
8942 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8943 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8945 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8946 int maxSizeOfArr=arrIn->getNumberOfTuples();
8947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8949 arrIo->alloc((int)(sz+1),1);
8950 int idsIt=idsOfSelectStart;
8951 int *work=arrIo->getPointer();
8954 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8956 if(idsIt>=0 && idsIt<nbOfGrps)
8957 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8960 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8961 throw INTERP_KERNEL::Exception(oss.str().c_str());
8967 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8968 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8969 throw INTERP_KERNEL::Exception(oss.str().c_str());
8972 arro->alloc(lgth,1);
8973 work=arro->getPointer();
8974 idsIt=idsOfSelectStart;
8975 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8977 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8978 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8981 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8982 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8983 throw INTERP_KERNEL::Exception(oss.str().c_str());
8987 arrIndexOut=arrIo.retn();
8991 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8992 * 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
8993 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8994 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8996 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8997 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8998 * \param [in] arrIn arr origin array from which the extraction will be done.
8999 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9000 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9001 * \param [in] srcArrIndex index array of \b srcArr
9002 * \param [out] arrOut the resulting array
9003 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9005 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9007 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9008 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9009 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9011 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9015 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9016 std::vector<bool> v(nbOfTuples,true);
9018 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9019 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9020 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9022 if(*it>=0 && *it<nbOfTuples)
9025 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9029 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9030 throw INTERP_KERNEL::Exception(oss.str().c_str());
9033 srcArrIndexPtr=srcArrIndex->getConstPointer();
9034 arrIo->alloc(nbOfTuples+1,1);
9035 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9036 const int *arrInPtr=arrIn->getConstPointer();
9037 const int *srcArrPtr=srcArr->getConstPointer();
9038 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9039 int *arroPtr=arro->getPointer();
9040 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9044 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9045 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9049 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9050 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9051 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9055 arrIndexOut=arrIo.retn();
9059 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9060 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9062 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9063 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9064 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9065 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9066 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9067 * \param [in] srcArrIndex index array of \b srcArr
9069 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9071 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9072 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9074 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9075 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9076 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9077 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9078 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9079 int *arrInOutPtr=arrInOut->getPointer();
9080 const int *srcArrPtr=srcArr->getConstPointer();
9081 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9083 if(*it>=0 && *it<nbOfTuples)
9085 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9086 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9089 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] !";
9090 throw INTERP_KERNEL::Exception(oss.str().c_str());
9095 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9096 throw INTERP_KERNEL::Exception(oss.str().c_str());
9102 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9103 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9104 * 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]].
9105 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9106 * A negative value in \b arrIn means that it is ignored.
9107 * 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.
9109 * \param [in] arrIn arr origin array from which the extraction will be done.
9110 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9111 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9112 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9114 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9116 int seed=0,nbOfDepthPeelingPerformed=0;
9117 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9121 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9122 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9123 * 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]].
9124 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9125 * A negative value in \b arrIn means that it is ignored.
9126 * 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.
9127 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9128 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
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 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9132 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9133 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9134 * \sa MEDCouplingUMesh::partitionBySpreadZone
9136 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9138 nbOfDepthPeelingPerformed=0;
9140 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9141 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9144 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9148 std::vector<bool> fetched(nbOfTuples,false);
9149 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9152 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9154 nbOfDepthPeelingPerformed=0;
9155 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9156 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9157 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9158 std::vector<bool> fetched2(nbOfTuples,false);
9160 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9162 if(*seedElt>=0 && *seedElt<nbOfTuples)
9163 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9165 { 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()); }
9167 const int *arrInPtr=arrIn->getConstPointer();
9168 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9169 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9170 std::vector<int> idsToFetch1(seedBg,seedEnd);
9171 std::vector<int> idsToFetch2;
9172 std::vector<int> *idsToFetch=&idsToFetch1;
9173 std::vector<int> *idsToFetchOther=&idsToFetch2;
9174 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9176 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9177 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9179 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9180 std::swap(idsToFetch,idsToFetchOther);
9181 idsToFetchOther->clear();
9182 nbOfDepthPeelingPerformed++;
9184 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9187 int *retPtr=ret->getPointer();
9188 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9195 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9196 * 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
9197 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9198 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9200 * \param [in] start begin of set of ids of the input extraction (included)
9201 * \param [in] end end of set of ids of the input extraction (excluded)
9202 * \param [in] step step of the set of ids in range mode.
9203 * \param [in] arrIn arr origin array from which the extraction will be done.
9204 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9205 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9206 * \param [in] srcArrIndex index array of \b srcArr
9207 * \param [out] arrOut the resulting array
9208 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9210 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9212 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9213 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9214 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9216 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9220 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9222 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9223 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9224 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9226 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9228 if(it>=0 && it<nbOfTuples)
9229 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9232 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9233 throw INTERP_KERNEL::Exception(oss.str().c_str());
9236 srcArrIndexPtr=srcArrIndex->getConstPointer();
9237 arrIo->alloc(nbOfTuples+1,1);
9238 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9239 const int *arrInPtr=arrIn->getConstPointer();
9240 const int *srcArrPtr=srcArr->getConstPointer();
9241 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9242 int *arroPtr=arro->getPointer();
9243 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9245 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9248 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9249 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9253 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9254 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9258 arrIndexOut=arrIo.retn();
9262 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9263 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9265 * \param [in] start begin of set of ids of the input extraction (included)
9266 * \param [in] end end of set of ids of the input extraction (excluded)
9267 * \param [in] step step of the set of ids in range mode.
9268 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9269 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9270 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9271 * \param [in] srcArrIndex index array of \b srcArr
9273 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9275 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9276 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9278 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9280 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9281 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9282 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9283 int *arrInOutPtr=arrInOut->getPointer();
9284 const int *srcArrPtr=srcArr->getConstPointer();
9285 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9287 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9289 if(it>=0 && it<nbOfTuples)
9291 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9292 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9295 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9296 throw INTERP_KERNEL::Exception(oss.str().c_str());
9301 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9302 throw INTERP_KERNEL::Exception(oss.str().c_str());
9308 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9309 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9310 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9311 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9312 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9314 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9316 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9318 checkFullyDefined();
9319 int mdim=getMeshDimension();
9320 int spaceDim=getSpaceDimension();
9322 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9323 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9324 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9325 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9326 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9327 ret->setCoords(getCoords());
9328 ret->allocateCells((int)partition.size());
9330 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9332 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9337 cell=tmp->buildUnionOf2DMesh();
9340 cell=tmp->buildUnionOf3DMesh();
9343 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9346 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9349 ret->finishInsertingCells();
9354 * This method partitions \b this into contiguous zone.
9355 * This method only needs a well defined connectivity. Coordinates are not considered here.
9356 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9358 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9360 int nbOfCellsCur=getNumberOfCells();
9361 std::vector<DataArrayInt *> ret;
9364 DataArrayInt *neigh=0,*neighI=0;
9365 computeNeighborsOfCells(neigh,neighI);
9366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9367 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9368 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9370 while(seed<nbOfCellsCur)
9372 int nbOfPeelPerformed=0;
9373 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9374 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9376 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9377 ret.push_back((*it).retn());
9382 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9383 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9385 * \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.
9386 * \return a newly allocated DataArrayInt to be managed by the caller.
9387 * \throw In case of \a code has not the right format (typically of size 3*n)
9389 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9392 std::size_t nb=code.size()/3;
9393 if(code.size()%3!=0)
9394 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9395 ret->alloc((int)nb,2);
9396 int *retPtr=ret->getPointer();
9397 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9399 retPtr[0]=code[3*i+2];
9400 retPtr[1]=code[3*i+2]+code[3*i+1];
9406 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9407 * All cells in \a this are expected to be linear 3D cells.
9408 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9409 * It leads to an increase to number of cells.
9410 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9411 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9412 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9414 * \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.
9415 * For all other cells, the splitting policy will be ignored.
9416 * \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.
9417 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9418 * an id of old cell producing it. The caller is to delete this array using
9419 * decrRef() as it is no more needed.
9420 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9422 * \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
9423 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9425 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9426 * \throw If \a this is not fully constituted with linear 3D cells.
9427 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9429 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9431 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9432 checkConnectivityFullyDefined();
9433 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9434 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9435 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9436 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9438 int *retPt(ret->getPointer());
9439 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9440 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9441 const int *oldc(_nodal_connec->begin());
9442 const int *oldci(_nodal_connec_index->begin());
9443 const double *coords(_coords->begin());
9444 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9446 std::vector<int> a; std::vector<double> b;
9447 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9448 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9449 const int *aa(&a[0]);
9452 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9454 *it=(-(*(it))-1+nbNodes);
9455 addPts->insertAtTheEnd(b.begin(),b.end());
9456 nbNodes+=(int)b.size()/3;
9458 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9459 newConn->insertAtTheEnd(aa,aa+4);
9461 if(!addPts->empty())
9463 addPts->rearrange(3);
9464 nbOfAdditionalPoints=addPts->getNumberOfTuples();
9465 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9466 ret0->setCoords(addPts);
9470 nbOfAdditionalPoints=0;
9471 ret0->setCoords(getCoords());
9473 ret0->setNodalConnectivity(newConn);
9475 ret->computeOffsets2();
9476 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9480 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9481 _own_cell(true),_cell_id(-1),_nb_cell(0)
9486 _nb_cell=mesh->getNumberOfCells();
9490 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9498 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9499 _own_cell(false),_cell_id(bg-1),
9506 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9509 if(_cell_id<_nb_cell)
9518 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9524 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9526 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9529 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9535 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9543 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9549 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9554 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9559 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9561 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9564 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9569 _nb_cell=mesh->getNumberOfCells();
9573 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9580 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9582 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9583 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9584 if(_cell_id<_nb_cell)
9586 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9587 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9588 int startId=_cell_id;
9589 _cell_id+=nbOfElems;
9590 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9596 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9600 _conn=mesh->getNodalConnectivity()->getPointer();
9601 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9605 void MEDCouplingUMeshCell::next()
9607 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9612 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9615 std::string MEDCouplingUMeshCell::repr() const
9617 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9619 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9621 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9625 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9628 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9630 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9631 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9633 return INTERP_KERNEL::NORM_ERROR;
9636 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9639 if(_conn_lgth!=NOTICABLE_FIRST_VAL)