1 // Copyright (C) 2007-2014 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, or (at your option) any later version.
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 std::string& 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,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());
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());
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(),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);
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);
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 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4025 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4027 * \warning This method is suitable if the caller intends to evaluate only one
4028 * point, for more points getCellsContainingPoints() is recommended as it is
4030 * \param [in] pos - array of coordinates of the ball central point.
4031 * \param [in] eps - ball radius.
4032 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4033 * if there are no such cells.
4034 * \throw If the coordinates array is not set.
4035 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4037 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4039 std::vector<int> elts;
4040 getCellsContainingPoint(pos,eps,elts);
4043 return elts.front();
4047 * Finds cells in contact with a ball (i.e. a point with precision).
4048 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4049 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4050 * \warning This method is suitable if the caller intends to evaluate only one
4051 * point, for more points getCellsContainingPoints() is recommended as it is
4053 * \param [in] pos - array of coordinates of the ball central point.
4054 * \param [in] eps - ball radius.
4055 * \param [out] elts - vector returning ids of the found cells. It is cleared
4056 * before inserting ids.
4057 * \throw If the coordinates array is not set.
4058 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4060 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4061 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4063 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4066 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4067 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4072 namespace ParaMEDMEM
4074 template<const int SPACEDIMM>
4078 static const int MY_SPACEDIM=SPACEDIMM;
4079 static const int MY_MESHDIM=8;
4080 typedef int MyConnType;
4081 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4083 // useless, but for windows compilation ...
4084 const double* getCoordinatesPtr() const { return 0; }
4085 const int* getConnectivityPtr() const { return 0; }
4086 const int* getConnectivityIndexPtr() const { return 0; }
4087 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4091 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4093 INTERP_KERNEL::Edge *ret=0;
4096 case INTERP_KERNEL::NORM_SEG2:
4098 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4101 case INTERP_KERNEL::NORM_SEG3:
4103 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4104 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4105 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4106 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4107 bool colinearity=inters.areColinears();
4108 delete e1; delete e2;
4110 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4112 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4113 mapp2[bg[2]].second=false;
4117 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4123 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4124 * the global mesh 'mDesc'.
4125 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4126 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4128 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4129 std::map<INTERP_KERNEL::Node *,int>& mapp)
4130 throw(INTERP_KERNEL::Exception)
4133 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.
4134 const double *coo=mDesc->getCoords()->getConstPointer();
4135 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4136 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4138 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4139 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4140 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4142 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4143 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4145 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4146 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4148 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4149 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4151 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4153 if((*it2).second.second)
4154 mapp[(*it2).second.first]=(*it2).first;
4155 ((*it2).second.first)->decrRef();
4160 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4164 int locId=nodeId-offset2;
4165 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4169 int locId=nodeId-offset1;
4170 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4172 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4176 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4178 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4179 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4180 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4182 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4184 int eltId1=abs(*desc1)-1;
4185 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4187 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4188 if(it==mappRev.end())
4190 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4201 template<int SPACEDIM>
4202 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4203 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4205 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4206 int *eltsIndexPtr(eltsIndex->getPointer());
4207 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4208 const double *bbox(bboxArr->begin());
4209 int nbOfCells=getNumberOfCells();
4210 const int *conn=_nodal_connec->getConstPointer();
4211 const int *connI=_nodal_connec_index->getConstPointer();
4212 double bb[2*SPACEDIM];
4213 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4214 for(int i=0;i<nbOfPoints;i++)
4216 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4217 for(int j=0;j<SPACEDIM;j++)
4219 bb[2*j]=pos[SPACEDIM*i+j];
4220 bb[2*j+1]=pos[SPACEDIM*i+j];
4222 std::vector<int> candidates;
4223 myTree.getIntersectingElems(bb,candidates);
4224 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4226 int sz(connI[(*iter)+1]-connI[*iter]-1);
4227 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4229 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4230 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4235 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4236 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4237 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4238 INTERP_KERNEL::QuadraticPolygon *pol(0);
4239 for(int j=0;j<sz;j++)
4241 int nodeId(conn[connI[*iter]+1+j]);
4242 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4244 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4245 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4247 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4248 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4249 double a(0.),b(0.),c(0.);
4250 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4251 status=pol->isInOrOut2(n);
4252 delete pol; n->decrRef();
4256 eltsIndexPtr[i+1]++;
4257 elts->pushBackSilent(*iter);
4263 * Finds cells in contact with several balls (i.e. points with precision).
4264 * This method is an extension of getCellContainingPoint() and
4265 * getCellsContainingPoint() for the case of multiple points.
4266 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4267 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4268 * \param [in] pos - an array of coordinates of points in full interlace mode :
4269 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4270 * this->getSpaceDimension() * \a nbOfPoints
4271 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4272 * \param [in] eps - radius of balls (i.e. the precision).
4273 * \param [out] elts - vector returning ids of found cells.
4274 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4275 * dividing cell ids in \a elts into groups each referring to one
4276 * point. Its every element (except the last one) is an index pointing to the
4277 * first id of a group of cells. For example cells in contact with the *i*-th
4278 * point are described by following range of indices:
4279 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4280 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4281 * Number of cells in contact with the *i*-th point is
4282 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4283 * \throw If the coordinates array is not set.
4284 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4286 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4287 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4289 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4292 int spaceDim=getSpaceDimension();
4293 int mDim=getMeshDimension();
4298 const double *coords=_coords->getConstPointer();
4299 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4306 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4308 else if(spaceDim==2)
4312 const double *coords=_coords->getConstPointer();
4313 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4316 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4318 else if(spaceDim==1)
4322 const double *coords=_coords->getConstPointer();
4323 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4326 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4333 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4334 * least two its edges intersect each other anywhere except their extremities. An
4335 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4336 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4337 * cleared before filling in.
4338 * \param [in] eps - precision.
4339 * \throw If \a this->getMeshDimension() != 2.
4340 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4342 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4344 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4345 if(getMeshDimension()!=2)
4346 throw INTERP_KERNEL::Exception(msg);
4347 int spaceDim=getSpaceDimension();
4348 if(spaceDim!=2 && spaceDim!=3)
4349 throw INTERP_KERNEL::Exception(msg);
4350 const int *conn=_nodal_connec->getConstPointer();
4351 const int *connI=_nodal_connec_index->getConstPointer();
4352 int nbOfCells=getNumberOfCells();
4353 std::vector<double> cell2DinS2;
4354 for(int i=0;i<nbOfCells;i++)
4356 int offset=connI[i];
4357 int nbOfNodesForCell=connI[i+1]-offset-1;
4358 if(nbOfNodesForCell<=3)
4360 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4361 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4362 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4369 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4371 * 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.
4372 * 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.
4374 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4375 * This convex envelop is computed using Jarvis march algorithm.
4376 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4377 * 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)
4378 * 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.
4380 * \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.
4382 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4384 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4385 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4386 checkFullyDefined();
4387 const double *coords=getCoords()->getConstPointer();
4388 int nbOfCells=getNumberOfCells();
4389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4390 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4392 int *workIndexOut=nodalConnecIndexOut->getPointer();
4394 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4395 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4396 std::set<INTERP_KERNEL::NormalizedCellType> types;
4397 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4398 isChanged->alloc(0,1);
4399 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4401 int pos=nodalConnecOut->getNumberOfTuples();
4402 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4403 isChanged->pushBackSilent(i);
4404 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4405 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4407 if(isChanged->empty())
4409 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4411 return isChanged.retn();
4415 * This method is \b NOT const because it can modify \a this.
4416 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4417 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4418 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4419 * \b 1 for translation and rotation around point of 'mesh1D'.
4420 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4422 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4424 checkFullyDefined();
4425 mesh1D->checkFullyDefined();
4426 if(!mesh1D->isContiguous1D())
4427 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4428 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4429 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4430 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4431 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4432 if(mesh1D->getMeshDimension()!=1)
4433 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4435 if(isPresenceOfQuadratic())
4437 if(mesh1D->isFullyQuadratic())
4440 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4443 int oldNbOfNodes=getNumberOfNodes();
4444 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4449 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4454 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4458 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4460 setCoords(newCoords);
4461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4467 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4468 * If it is not the case an exception will be thrown.
4469 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4470 * intersection of plane defined by ('origin','vec').
4471 * This method has one in/out parameter : 'cut3DCurve'.
4472 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4473 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4474 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4475 * This method will throw an exception if \a this contains a non linear segment.
4477 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4479 checkFullyDefined();
4480 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4481 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4482 int ncells=getNumberOfCells();
4483 int nnodes=getNumberOfNodes();
4484 double vec2[3],vec3[3],vec4[3];
4485 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4487 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4488 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4489 const int *conn=_nodal_connec->getConstPointer();
4490 const int *connI=_nodal_connec_index->getConstPointer();
4491 const double *coo=_coords->getConstPointer();
4492 std::vector<double> addCoo;
4493 for(int i=0;i<ncells;i++)
4495 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4497 if(cut3DCurve[i]==-2)
4499 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4500 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];
4501 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4502 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4503 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4505 const double *st2=coo+3*st;
4506 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4507 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]));
4508 if(pos>eps && pos<1-eps)
4510 int nNode=((int)addCoo.size())/3;
4511 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4512 addCoo.insert(addCoo.end(),vec4,vec4+3);
4513 cut3DCurve[i]=nnodes+nNode;
4519 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4523 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4524 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4525 coo2->alloc(newNbOfNodes,3);
4526 double *tmp=coo2->getPointer();
4527 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4528 std::copy(addCoo.begin(),addCoo.end(),tmp);
4529 DataArrayDouble::SetArrayIn(coo2,_coords);
4534 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4535 * \param mesh1D is the input 1D mesh used for translation computation.
4536 * \return newCoords new coords filled by this method.
4538 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4540 int oldNbOfNodes=getNumberOfNodes();
4541 int nbOf1DCells=mesh1D->getNumberOfCells();
4542 int spaceDim=getSpaceDimension();
4543 DataArrayDouble *ret=DataArrayDouble::New();
4544 std::vector<bool> isQuads;
4545 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4546 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4547 double *retPtr=ret->getPointer();
4548 const double *coords=getCoords()->getConstPointer();
4549 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4551 std::vector<double> c;
4555 for(int i=0;i<nbOf1DCells;i++)
4558 mesh1D->getNodeIdsOfCell(i,v);
4560 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4561 mesh1D->getCoordinatesOfNode(v[0],c);
4562 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4563 for(int j=0;j<oldNbOfNodes;j++)
4564 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4568 mesh1D->getCoordinatesOfNode(v[1],c);
4569 mesh1D->getCoordinatesOfNode(v[0],c);
4570 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4571 for(int j=0;j<oldNbOfNodes;j++)
4572 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4575 ret->copyStringInfoFrom(*getCoords());
4580 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4581 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4582 * \return newCoords new coords filled by this method.
4584 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4586 if(mesh1D->getSpaceDimension()==2)
4587 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4588 if(mesh1D->getSpaceDimension()==3)
4589 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4590 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4594 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4595 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4596 * \return newCoords new coords filled by this method.
4598 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4601 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4602 int oldNbOfNodes=getNumberOfNodes();
4603 int nbOf1DCells=mesh1D->getNumberOfCells();
4605 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4606 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4607 int nbOfLevsInVec=nbOf1DCells+1;
4608 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4609 double *retPtr=ret->getPointer();
4610 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4611 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4612 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4613 tmp->setCoords(tmp2);
4614 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4615 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4616 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4617 for(int i=1;i<nbOfLevsInVec;i++)
4619 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4620 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4621 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4622 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4623 tmp->translate(vec);
4624 double tmp3[2],radius,alpha,alpha0;
4625 const double *p0=i+1<nbOfLevsInVec?begin:third;
4626 const double *p1=i+1<nbOfLevsInVec?end:begin;
4627 const double *p2=i+1<nbOfLevsInVec?third:end;
4628 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4629 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]);
4630 double angle=acos(cosangle/(radius*radius));
4631 tmp->rotate(end,0,angle);
4632 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4638 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4639 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4640 * \return newCoords new coords filled by this method.
4642 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4645 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4646 int oldNbOfNodes=getNumberOfNodes();
4647 int nbOf1DCells=mesh1D->getNumberOfCells();
4649 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4650 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4651 int nbOfLevsInVec=nbOf1DCells+1;
4652 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4653 double *retPtr=ret->getPointer();
4654 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4655 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4656 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4657 tmp->setCoords(tmp2);
4658 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4659 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4660 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4661 for(int i=1;i<nbOfLevsInVec;i++)
4663 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4664 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4665 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4666 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4667 tmp->translate(vec);
4668 double tmp3[2],radius,alpha,alpha0;
4669 const double *p0=i+1<nbOfLevsInVec?begin:third;
4670 const double *p1=i+1<nbOfLevsInVec?end:begin;
4671 const double *p2=i+1<nbOfLevsInVec?third:end;
4672 double vecPlane[3]={
4673 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4674 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4675 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4677 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4680 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4681 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4682 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4684 double c2=cos(asin(s2));
4686 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4687 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4688 {-vec2[1]*s2, vec2[0]*s2, c2}
4690 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]};
4691 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]};
4692 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]};
4693 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4694 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]);
4695 double angle=acos(cosangle/(radius*radius));
4696 tmp->rotate(end,vecPlane,angle);
4699 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4705 * This method is private because not easy to use for end user. This method is const contrary to
4706 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4707 * the coords sorted slice by slice.
4708 * \param isQuad specifies presence of quadratic cells.
4710 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4712 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4713 int nbOf2DCells=getNumberOfCells();
4714 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4715 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4716 const int *conn=_nodal_connec->getConstPointer();
4717 const int *connI=_nodal_connec_index->getConstPointer();
4718 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4719 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4720 newConnI->alloc(nbOf3DCells+1,1);
4721 int *newConnIPtr=newConnI->getPointer();
4723 std::vector<int> newc;
4724 for(int j=0;j<nbOf2DCells;j++)
4726 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4727 *newConnIPtr++=(int)newc.size();
4729 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4730 int *newConnPtr=newConn->getPointer();
4731 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4732 newConnIPtr=newConnI->getPointer();
4733 for(int iz=0;iz<nbOf1DCells;iz++)
4736 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4737 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4739 int icell=(int)(iter-newc.begin());
4740 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4743 *newConnPtr=(*iter)+iz*deltaPerLev;
4748 *newConnPtr=(*iter);
4751 ret->setConnectivity(newConn,newConnI,true);
4752 ret->setCoords(getCoords());
4757 * Checks if \a this mesh is constituted by only quadratic cells.
4758 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4759 * \throw If the coordinates array is not set.
4760 * \throw If the nodal connectivity of cells is not defined.
4762 bool MEDCouplingUMesh::isFullyQuadratic() const
4764 checkFullyDefined();
4766 int nbOfCells=getNumberOfCells();
4767 for(int i=0;i<nbOfCells && ret;i++)
4769 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4770 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4771 ret=cm.isQuadratic();
4777 * Checks if \a this mesh includes any quadratic cell.
4778 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4779 * \throw If the coordinates array is not set.
4780 * \throw If the nodal connectivity of cells is not defined.
4782 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4784 checkFullyDefined();
4786 int nbOfCells=getNumberOfCells();
4787 for(int i=0;i<nbOfCells && !ret;i++)
4789 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4790 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4791 ret=cm.isQuadratic();
4797 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4798 * this mesh, it remains unchanged.
4799 * \throw If the coordinates array is not set.
4800 * \throw If the nodal connectivity of cells is not defined.
4802 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4804 checkFullyDefined();
4805 int nbOfCells=getNumberOfCells();
4807 const int *iciptr=_nodal_connec_index->getConstPointer();
4808 for(int i=0;i<nbOfCells;i++)
4810 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4811 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4812 if(cm.isQuadratic())
4814 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4815 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4816 if(!cml.isDynamic())
4817 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4819 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4824 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4825 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4826 const int *icptr=_nodal_connec->getConstPointer();
4827 newConn->alloc(getMeshLength()-delta,1);
4828 newConnI->alloc(nbOfCells+1,1);
4829 int *ocptr=newConn->getPointer();
4830 int *ociptr=newConnI->getPointer();
4833 for(int i=0;i<nbOfCells;i++,ociptr++)
4835 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4836 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4837 if(!cm.isQuadratic())
4839 _types.insert(type);
4840 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4841 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4845 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4846 _types.insert(typel);
4847 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4848 int newNbOfNodes=cml.getNumberOfNodes();
4850 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4851 *ocptr++=(int)typel;
4852 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4853 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4856 setConnectivity(newConn,newConnI,false);
4860 * This method converts all linear cell in \a this to quadratic one.
4861 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4862 * 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)
4863 * 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.
4864 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4865 * end of the existing coordinates.
4867 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4868 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4869 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4871 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4873 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4875 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4877 DataArrayInt *conn=0,*connI=0;
4878 DataArrayDouble *coords=0;
4879 std::set<INTERP_KERNEL::NormalizedCellType> types;
4880 checkFullyDefined();
4881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4882 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4883 int meshDim=getMeshDimension();
4884 switch(conversionType)
4890 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4891 connSafe=conn; connISafe=connI; coordsSafe=coords;
4894 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4895 connSafe=conn; connISafe=connI; coordsSafe=coords;
4898 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4899 connSafe=conn; connISafe=connI; coordsSafe=coords;
4902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4910 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4911 connSafe=conn; connISafe=connI; coordsSafe=coords;
4914 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4915 connSafe=conn; connISafe=connI; coordsSafe=coords;
4918 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4919 connSafe=conn; connISafe=connI; coordsSafe=coords;
4922 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4927 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4929 setConnectivity(connSafe,connISafe,false);
4931 setCoords(coordsSafe);
4936 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4937 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4938 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4940 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4942 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4943 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4944 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4945 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4946 int nbOfCells=getNumberOfCells();
4947 int nbOfNodes=getNumberOfNodes();
4948 const int *cPtr=_nodal_connec->getConstPointer();
4949 const int *icPtr=_nodal_connec_index->getConstPointer();
4950 int lastVal=0,offset=nbOfNodes;
4951 for(int i=0;i<nbOfCells;i++,icPtr++)
4953 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4954 if(type==INTERP_KERNEL::NORM_SEG2)
4956 types.insert(INTERP_KERNEL::NORM_SEG3);
4957 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4958 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4959 newConn->pushBackSilent(offset++);
4961 newConnI->pushBackSilent(lastVal);
4962 ret->pushBackSilent(i);
4967 lastVal+=(icPtr[1]-icPtr[0]);
4968 newConnI->pushBackSilent(lastVal);
4969 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4972 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4973 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4977 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
4979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4980 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4983 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4984 DataArrayInt *conn1D=0,*conn1DI=0;
4985 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4986 DataArrayDouble *coordsTmp=0;
4987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4988 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4990 const int *c1DPtr=conn1D->begin();
4991 const int *c1DIPtr=conn1DI->begin();
4992 int nbOfCells=getNumberOfCells();
4993 const int *cPtr=_nodal_connec->getConstPointer();
4994 const int *icPtr=_nodal_connec_index->getConstPointer();
4996 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4998 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4999 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5000 if(!cm.isQuadratic())
5002 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5003 types.insert(typ2); newConn->pushBackSilent(typ2);
5004 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5005 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5006 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5007 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5008 newConnI->pushBackSilent(lastVal);
5009 ret->pushBackSilent(i);
5014 lastVal+=(icPtr[1]-icPtr[0]);
5015 newConnI->pushBackSilent(lastVal);
5016 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5019 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5024 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5025 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5026 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5028 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5032 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5033 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5036 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5039 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5041 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5042 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5043 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5045 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5046 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5047 DataArrayInt *conn1D=0,*conn1DI=0;
5048 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5049 DataArrayDouble *coordsTmp=0;
5050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5051 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5053 const int *c1DPtr=conn1D->begin();
5054 const int *c1DIPtr=conn1DI->begin();
5055 int nbOfCells=getNumberOfCells();
5056 const int *cPtr=_nodal_connec->getConstPointer();
5057 const int *icPtr=_nodal_connec_index->getConstPointer();
5058 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5059 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5061 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5062 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5063 if(!cm.isQuadratic())
5065 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5066 types.insert(typ2); newConn->pushBackSilent(typ2);
5067 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5068 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5069 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5070 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5071 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5072 newConnI->pushBackSilent(lastVal);
5073 ret->pushBackSilent(i);
5078 lastVal+=(icPtr[1]-icPtr[0]);
5079 newConnI->pushBackSilent(lastVal);
5080 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5083 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5084 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5089 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5090 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5091 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5093 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5096 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5097 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5100 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5103 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5105 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5107 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5109 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5111 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5112 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5113 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5114 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5115 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5117 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5118 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5120 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5122 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5123 int nbOfCells=getNumberOfCells();
5124 const int *cPtr=_nodal_connec->getConstPointer();
5125 const int *icPtr=_nodal_connec_index->getConstPointer();
5126 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5127 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5129 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5130 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5131 if(!cm.isQuadratic())
5133 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5134 if(typ2==INTERP_KERNEL::NORM_ERROR)
5136 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5137 throw INTERP_KERNEL::Exception(oss.str().c_str());
5139 types.insert(typ2); newConn->pushBackSilent(typ2);
5140 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5141 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5142 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5143 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5145 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5146 int tmpPos=newConn->getNumberOfTuples();
5147 newConn->pushBackSilent(nodeId2);
5148 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5150 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5151 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5152 newConnI->pushBackSilent(lastVal);
5153 ret->pushBackSilent(i);
5158 lastVal+=(icPtr[1]-icPtr[0]);
5159 newConnI->pushBackSilent(lastVal);
5160 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5165 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5166 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5167 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5168 int *c=newConn->getPointer();
5169 const int *cI(newConnI->begin());
5170 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5171 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5172 offset=coordsTmp2Safe->getNumberOfTuples();
5173 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5174 c[cI[(*elt)+1]-1]+=offset;
5175 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5180 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5181 * so that the number of cells remains the same. Quadratic faces are converted to
5182 * polygons. This method works only for 2D meshes in
5183 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5184 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5185 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5186 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5187 * a polylinized edge constituting the input polygon.
5188 * \throw If the coordinates array is not set.
5189 * \throw If the nodal connectivity of cells is not defined.
5190 * \throw If \a this->getMeshDimension() != 2.
5191 * \throw If \a this->getSpaceDimension() != 2.
5193 void MEDCouplingUMesh::tessellate2D(double eps)
5195 checkFullyDefined();
5196 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5198 double epsa=fabs(eps);
5199 if(epsa<std::numeric_limits<double>::min())
5200 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 !");
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5202 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5203 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5204 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5205 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5206 revDesc1=0; revDescIndx1=0;
5207 mDesc->tessellate2DCurve(eps);
5208 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5209 setCoords(mDesc->getCoords());
5213 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5214 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5215 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5216 * a sub-divided edge.
5217 * \throw If the coordinates array is not set.
5218 * \throw If the nodal connectivity of cells is not defined.
5219 * \throw If \a this->getMeshDimension() != 1.
5220 * \throw If \a this->getSpaceDimension() != 2.
5222 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5224 checkFullyDefined();
5225 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5226 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5227 double epsa=fabs(eps);
5228 if(epsa<std::numeric_limits<double>::min())
5229 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 !");
5230 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5231 int nbCells=getNumberOfCells();
5232 int nbNodes=getNumberOfNodes();
5233 const int *conn=_nodal_connec->getConstPointer();
5234 const int *connI=_nodal_connec_index->getConstPointer();
5235 const double *coords=_coords->getConstPointer();
5236 std::vector<double> addCoo;
5237 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5239 newConnI->alloc(nbCells+1,1);
5240 int *newConnIPtr=newConnI->getPointer();
5243 INTERP_KERNEL::Node *tmp2[3];
5244 std::set<INTERP_KERNEL::NormalizedCellType> types;
5245 for(int i=0;i<nbCells;i++,newConnIPtr++)
5247 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5248 if(cm.isQuadratic())
5249 {//assert(connI[i+1]-connI[i]-1==3)
5250 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5251 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5252 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5253 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5254 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5257 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5258 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5260 newConnIPtr[1]=(int)newConn.size();
5264 types.insert(INTERP_KERNEL::NORM_SEG2);
5265 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5266 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5267 newConnIPtr[1]=newConnIPtr[0]+3;
5272 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5273 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5274 newConnIPtr[1]=newConnIPtr[0]+3;
5277 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5280 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5282 newConnArr->alloc((int)newConn.size(),1);
5283 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5284 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5285 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5286 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5287 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5288 std::copy(addCoo.begin(),addCoo.end(),work);
5289 DataArrayDouble::SetArrayIn(newCoords,_coords);
5294 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5295 * In addition, returns an array mapping new cells to old ones. <br>
5296 * This method typically increases the number of cells in \a this mesh
5297 * but the number of nodes remains \b unchanged.
5298 * That's why the 3D splitting policies
5299 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5300 * \param [in] policy - specifies a pattern used for splitting.
5301 * The semantic of \a policy is:
5302 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5303 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5304 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5305 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5306 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5307 * an id of old cell producing it. The caller is to delete this array using
5308 * decrRef() as it is no more needed.
5309 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5310 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5311 * and \a this->getMeshDimension() != 3.
5312 * \throw If \a policy is not one of the four discussed above.
5313 * \throw If the nodal connectivity of cells is not defined.
5314 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5316 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5321 return simplexizePol0();
5323 return simplexizePol1();
5324 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5325 return simplexizePlanarFace5();
5326 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5327 return simplexizePlanarFace6();
5329 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)");
5334 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5335 * - 1D: INTERP_KERNEL::NORM_SEG2
5336 * - 2D: INTERP_KERNEL::NORM_TRI3
5337 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5339 * This method is useful for users that need to use P1 field services as
5340 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5341 * All these methods need mesh support containing only simplex cells.
5342 * \return bool - \c true if there are only simplex cells in \a this mesh.
5343 * \throw If the coordinates array is not set.
5344 * \throw If the nodal connectivity of cells is not defined.
5345 * \throw If \a this->getMeshDimension() < 1.
5347 bool MEDCouplingUMesh::areOnlySimplexCells() const
5349 checkFullyDefined();
5350 int mdim=getMeshDimension();
5351 if(mdim<1 || mdim>3)
5352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5353 int nbCells=getNumberOfCells();
5354 const int *conn=_nodal_connec->getConstPointer();
5355 const int *connI=_nodal_connec_index->getConstPointer();
5356 for(int i=0;i<nbCells;i++)
5358 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5366 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5368 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5370 checkConnectivityFullyDefined();
5371 if(getMeshDimension()!=2)
5372 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5373 int nbOfCells=getNumberOfCells();
5374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5375 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5376 ret->alloc(nbOfCells+nbOfCutCells,1);
5377 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5378 int *retPt=ret->getPointer();
5379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5381 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5382 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5383 int *pt=newConn->getPointer();
5384 int *ptI=newConnI->getPointer();
5386 const int *oldc=_nodal_connec->getConstPointer();
5387 const int *ci=_nodal_connec_index->getConstPointer();
5388 for(int i=0;i<nbOfCells;i++,ci++)
5390 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5392 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5393 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5394 pt=std::copy(tmp,tmp+8,pt);
5403 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5404 ptI[1]=ptI[0]+ci[1]-ci[0];
5409 _nodal_connec->decrRef();
5410 _nodal_connec=newConn.retn();
5411 _nodal_connec_index->decrRef();
5412 _nodal_connec_index=newConnI.retn();
5419 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5421 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5423 checkConnectivityFullyDefined();
5424 if(getMeshDimension()!=2)
5425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5426 int nbOfCells=getNumberOfCells();
5427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5428 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5429 ret->alloc(nbOfCells+nbOfCutCells,1);
5430 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5431 int *retPt=ret->getPointer();
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5434 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5435 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5436 int *pt=newConn->getPointer();
5437 int *ptI=newConnI->getPointer();
5439 const int *oldc=_nodal_connec->getConstPointer();
5440 const int *ci=_nodal_connec_index->getConstPointer();
5441 for(int i=0;i<nbOfCells;i++,ci++)
5443 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5445 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5446 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5447 pt=std::copy(tmp,tmp+8,pt);
5456 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5457 ptI[1]=ptI[0]+ci[1]-ci[0];
5462 _nodal_connec->decrRef();
5463 _nodal_connec=newConn.retn();
5464 _nodal_connec_index->decrRef();
5465 _nodal_connec_index=newConnI.retn();
5472 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5474 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5476 checkConnectivityFullyDefined();
5477 if(getMeshDimension()!=3)
5478 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5479 int nbOfCells=getNumberOfCells();
5480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5481 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5482 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5483 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5484 int *retPt=ret->getPointer();
5485 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5487 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5488 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5489 int *pt=newConn->getPointer();
5490 int *ptI=newConnI->getPointer();
5492 const int *oldc=_nodal_connec->getConstPointer();
5493 const int *ci=_nodal_connec_index->getConstPointer();
5494 for(int i=0;i<nbOfCells;i++,ci++)
5496 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5498 for(int j=0;j<5;j++,pt+=5,ptI++)
5500 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5501 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];
5508 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5509 ptI[1]=ptI[0]+ci[1]-ci[0];
5514 _nodal_connec->decrRef();
5515 _nodal_connec=newConn.retn();
5516 _nodal_connec_index->decrRef();
5517 _nodal_connec_index=newConnI.retn();
5524 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5526 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5528 checkConnectivityFullyDefined();
5529 if(getMeshDimension()!=3)
5530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5531 int nbOfCells=getNumberOfCells();
5532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5533 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5534 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5535 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5536 int *retPt=ret->getPointer();
5537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5539 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5540 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5541 int *pt=newConn->getPointer();
5542 int *ptI=newConnI->getPointer();
5544 const int *oldc=_nodal_connec->getConstPointer();
5545 const int *ci=_nodal_connec_index->getConstPointer();
5546 for(int i=0;i<nbOfCells;i++,ci++)
5548 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5550 for(int j=0;j<6;j++,pt+=5,ptI++)
5552 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5553 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];
5560 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5561 ptI[1]=ptI[0]+ci[1]-ci[0];
5566 _nodal_connec->decrRef();
5567 _nodal_connec=newConn.retn();
5568 _nodal_connec_index->decrRef();
5569 _nodal_connec_index=newConnI.retn();
5576 * 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.
5577 * This method completly ignore coordinates.
5578 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5579 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5580 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5581 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5583 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5585 checkFullyDefined();
5586 if(getMeshDimension()!=2)
5587 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5588 int nbOfCells=getNumberOfCells();
5589 int *connI=_nodal_connec_index->getPointer();
5591 for(int i=0;i<nbOfCells;i++,connI++)
5593 int offset=descIndex[i];
5594 int nbOfEdges=descIndex[i+1]-offset;
5596 bool ddirect=desc[offset+nbOfEdges-1]>0;
5597 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5598 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5599 for(int j=0;j<nbOfEdges;j++)
5601 bool direct=desc[offset+j]>0;
5602 int edgeId=std::abs(desc[offset+j])-1;
5603 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5605 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5606 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5607 int ref2=direct?id1:id2;
5610 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5611 newConnLgth+=nbOfSubNodes-1;
5616 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5617 throw INTERP_KERNEL::Exception(oss.str().c_str());
5622 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5625 newConnLgth++;//+1 is for cell type
5626 connI[1]=newConnLgth;
5629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5630 newConn->alloc(newConnLgth,1);
5631 int *work=newConn->getPointer();
5632 for(int i=0;i<nbOfCells;i++)
5634 *work++=INTERP_KERNEL::NORM_POLYGON;
5635 int offset=descIndex[i];
5636 int nbOfEdges=descIndex[i+1]-offset;
5637 for(int j=0;j<nbOfEdges;j++)
5639 bool direct=desc[offset+j]>0;
5640 int edgeId=std::abs(desc[offset+j])-1;
5642 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5645 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5646 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5647 work=std::copy(it,it+nbOfSubNodes-1,work);
5651 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5654 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5658 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5659 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5660 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5661 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5662 * so it can be useful to call mergeNodes() before calling this method.
5663 * \throw If \a this->getMeshDimension() <= 1.
5664 * \throw If the coordinates array is not set.
5665 * \throw If the nodal connectivity of cells is not defined.
5667 void MEDCouplingUMesh::convertDegeneratedCells()
5669 checkFullyDefined();
5670 if(getMeshDimension()<=1)
5671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5672 int nbOfCells=getNumberOfCells();
5675 int initMeshLgth=getMeshLength();
5676 int *conn=_nodal_connec->getPointer();
5677 int *index=_nodal_connec_index->getPointer();
5681 for(int i=0;i<nbOfCells;i++)
5683 lgthOfCurCell=index[i+1]-posOfCurCell;
5684 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5686 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5687 conn+newPos+1,newLgth);
5688 conn[newPos]=newType;
5690 posOfCurCell=index[i+1];
5693 if(newPos!=initMeshLgth)
5694 _nodal_connec->reAlloc(newPos);
5699 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5700 * A cell is considered to be oriented correctly if an angle between its
5701 * normal vector and a given vector is less than \c PI / \c 2.
5702 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5704 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5706 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5707 * is not cleared before filling in.
5708 * \throw If \a this->getMeshDimension() != 2.
5709 * \throw If \a this->getSpaceDimension() != 3.
5711 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5712 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5714 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5716 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5717 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5718 int nbOfCells=getNumberOfCells();
5719 const int *conn=_nodal_connec->getConstPointer();
5720 const int *connI=_nodal_connec_index->getConstPointer();
5721 const double *coordsPtr=_coords->getConstPointer();
5722 for(int i=0;i<nbOfCells;i++)
5724 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5725 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5727 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5728 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5735 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5736 * considered to be oriented correctly if an angle between its normal vector and a
5737 * given vector is less than \c PI / \c 2.
5738 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5740 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5742 * \throw If \a this->getMeshDimension() != 2.
5743 * \throw If \a this->getSpaceDimension() != 3.
5745 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5746 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5748 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5750 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5751 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5752 int nbOfCells=getNumberOfCells();
5753 int *conn=_nodal_connec->getPointer();
5754 const int *connI=_nodal_connec_index->getConstPointer();
5755 const double *coordsPtr=_coords->getConstPointer();
5756 bool isModified=false;
5757 for(int i=0;i<nbOfCells;i++)
5759 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5760 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5762 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5763 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5768 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5769 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5770 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5774 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5775 std::vector<int> tmp0(sz-1),tmp1(sz);
5776 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5777 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5778 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5779 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5785 _nodal_connec->declareAsNew();
5790 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5791 * oriented facets. The normal vector of the facet should point out of the cell.
5792 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5793 * is not cleared before filling in.
5794 * \throw If \a this->getMeshDimension() != 3.
5795 * \throw If \a this->getSpaceDimension() != 3.
5796 * \throw If the coordinates array is not set.
5797 * \throw If the nodal connectivity of cells is not defined.
5799 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5800 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5802 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5804 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5805 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5806 int nbOfCells=getNumberOfCells();
5807 const int *conn=_nodal_connec->getConstPointer();
5808 const int *connI=_nodal_connec_index->getConstPointer();
5809 const double *coordsPtr=_coords->getConstPointer();
5810 for(int i=0;i<nbOfCells;i++)
5812 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5813 if(type==INTERP_KERNEL::NORM_POLYHED)
5815 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5822 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5824 * \throw If \a this->getMeshDimension() != 3.
5825 * \throw If \a this->getSpaceDimension() != 3.
5826 * \throw If the coordinates array is not set.
5827 * \throw If the nodal connectivity of cells is not defined.
5828 * \throw If the reparation fails.
5830 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5831 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5832 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5834 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5836 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5837 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5838 int nbOfCells=getNumberOfCells();
5839 int *conn=_nodal_connec->getPointer();
5840 const int *connI=_nodal_connec_index->getConstPointer();
5841 const double *coordsPtr=_coords->getConstPointer();
5842 for(int i=0;i<nbOfCells;i++)
5844 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5845 if(type==INTERP_KERNEL::NORM_POLYHED)
5849 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5850 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5852 catch(INTERP_KERNEL::Exception& e)
5854 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5855 throw INTERP_KERNEL::Exception(oss.str().c_str());
5863 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5864 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5865 * according to which the first facet of the cell should be oriented to have the normal vector
5866 * pointing out of cell.
5867 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5868 * cells. The caller is to delete this array using decrRef() as it is no more
5870 * \throw If \a this->getMeshDimension() != 3.
5871 * \throw If \a this->getSpaceDimension() != 3.
5872 * \throw If the coordinates array is not set.
5873 * \throw If the nodal connectivity of cells is not defined.
5875 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5876 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5877 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5879 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5881 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5882 if(getMeshDimension()!=3)
5883 throw INTERP_KERNEL::Exception(msg);
5884 int spaceDim=getSpaceDimension();
5886 throw INTERP_KERNEL::Exception(msg);
5888 int nbOfCells=getNumberOfCells();
5889 int *conn=_nodal_connec->getPointer();
5890 const int *connI=_nodal_connec_index->getConstPointer();
5891 const double *coo=getCoords()->getConstPointer();
5892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5893 for(int i=0;i<nbOfCells;i++)
5895 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5896 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5898 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5900 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5901 cells->pushBackSilent(i);
5905 return cells.retn();
5909 * This method is a faster method to correct orientation of all 3D cells in \a this.
5910 * 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.
5911 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5913 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5914 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5916 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5918 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5919 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5920 int nbOfCells=getNumberOfCells();
5921 int *conn=_nodal_connec->getPointer();
5922 const int *connI=_nodal_connec_index->getConstPointer();
5923 const double *coordsPtr=_coords->getConstPointer();
5924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5925 for(int i=0;i<nbOfCells;i++)
5927 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5930 case INTERP_KERNEL::NORM_TETRA4:
5932 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5934 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5935 ret->pushBackSilent(i);
5939 case INTERP_KERNEL::NORM_PYRA5:
5941 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5943 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5944 ret->pushBackSilent(i);
5948 case INTERP_KERNEL::NORM_PENTA6:
5949 case INTERP_KERNEL::NORM_HEXA8:
5950 case INTERP_KERNEL::NORM_HEXGP12:
5952 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5954 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5955 ret->pushBackSilent(i);
5959 case INTERP_KERNEL::NORM_POLYHED:
5961 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5963 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5964 ret->pushBackSilent(i);
5969 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 !");
5977 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5978 * If it is not the case an exception will be thrown.
5979 * This method is fast because the first cell of \a this is used to compute the plane.
5980 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5981 * \param pos output of size at least 3 used to store a point owned of searched plane.
5983 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5985 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5986 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5987 const int *conn=_nodal_connec->getConstPointer();
5988 const int *connI=_nodal_connec_index->getConstPointer();
5989 const double *coordsPtr=_coords->getConstPointer();
5990 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5991 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5995 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5996 * cells. Currently cells of the following types are treated:
5997 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5998 * For a cell of other type an exception is thrown.
5999 * Space dimension of a 2D mesh can be either 2 or 3.
6000 * The Edge Ratio of a cell \f$t\f$ is:
6001 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6002 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6003 * the smallest edge lengths of \f$t\f$.
6004 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6005 * cells and one time, lying on \a this mesh. The caller is to delete this
6006 * field using decrRef() as it is no more needed.
6007 * \throw If the coordinates array is not set.
6008 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6009 * \throw If the connectivity data array has more than one component.
6010 * \throw If the connectivity data array has a named component.
6011 * \throw If the connectivity index data array has more than one component.
6012 * \throw If the connectivity index data array has a named component.
6013 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6014 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6015 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6017 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6020 int spaceDim=getSpaceDimension();
6021 int meshDim=getMeshDimension();
6022 if(spaceDim!=2 && spaceDim!=3)
6023 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6024 if(meshDim!=2 && meshDim!=3)
6025 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6026 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6028 int nbOfCells=getNumberOfCells();
6029 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6030 arr->alloc(nbOfCells,1);
6031 double *pt=arr->getPointer();
6032 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6033 const int *conn=_nodal_connec->getConstPointer();
6034 const int *connI=_nodal_connec_index->getConstPointer();
6035 const double *coo=_coords->getConstPointer();
6037 for(int i=0;i<nbOfCells;i++,pt++)
6039 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6042 case INTERP_KERNEL::NORM_TRI3:
6044 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6045 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6048 case INTERP_KERNEL::NORM_QUAD4:
6050 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6051 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6054 case INTERP_KERNEL::NORM_TETRA4:
6056 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6057 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6063 conn+=connI[i+1]-connI[i];
6065 ret->setName("EdgeRatio");
6066 ret->synchronizeTimeWithSupport();
6071 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6072 * cells. Currently cells of the following types are treated:
6073 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6074 * For a cell of other type an exception is thrown.
6075 * Space dimension of a 2D mesh can be either 2 or 3.
6076 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6077 * cells and one time, lying on \a this mesh. The caller is to delete this
6078 * field using decrRef() as it is no more needed.
6079 * \throw If the coordinates array is not set.
6080 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6081 * \throw If the connectivity data array has more than one component.
6082 * \throw If the connectivity data array has a named component.
6083 * \throw If the connectivity index data array has more than one component.
6084 * \throw If the connectivity index data array has a named component.
6085 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6086 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6087 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6089 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6092 int spaceDim=getSpaceDimension();
6093 int meshDim=getMeshDimension();
6094 if(spaceDim!=2 && spaceDim!=3)
6095 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6096 if(meshDim!=2 && meshDim!=3)
6097 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6098 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6100 int nbOfCells=getNumberOfCells();
6101 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6102 arr->alloc(nbOfCells,1);
6103 double *pt=arr->getPointer();
6104 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6105 const int *conn=_nodal_connec->getConstPointer();
6106 const int *connI=_nodal_connec_index->getConstPointer();
6107 const double *coo=_coords->getConstPointer();
6109 for(int i=0;i<nbOfCells;i++,pt++)
6111 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6114 case INTERP_KERNEL::NORM_TRI3:
6116 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6117 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6120 case INTERP_KERNEL::NORM_QUAD4:
6122 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6123 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6126 case INTERP_KERNEL::NORM_TETRA4:
6128 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6129 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6133 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6135 conn+=connI[i+1]-connI[i];
6137 ret->setName("AspectRatio");
6138 ret->synchronizeTimeWithSupport();
6143 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6144 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6145 * treated: INTERP_KERNEL::NORM_QUAD4.
6146 * For a cell of other type an exception is thrown.
6147 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6148 * cells and one time, lying on \a this mesh. The caller is to delete this
6149 * field using decrRef() as it is no more needed.
6150 * \throw If the coordinates array is not set.
6151 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6152 * \throw If the connectivity data array has more than one component.
6153 * \throw If the connectivity data array has a named component.
6154 * \throw If the connectivity index data array has more than one component.
6155 * \throw If the connectivity index data array has a named component.
6156 * \throw If \a this->getMeshDimension() != 2.
6157 * \throw If \a this->getSpaceDimension() != 3.
6158 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6160 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6163 int spaceDim=getSpaceDimension();
6164 int meshDim=getMeshDimension();
6166 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6168 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6169 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6171 int nbOfCells=getNumberOfCells();
6172 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6173 arr->alloc(nbOfCells,1);
6174 double *pt=arr->getPointer();
6175 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6176 const int *conn=_nodal_connec->getConstPointer();
6177 const int *connI=_nodal_connec_index->getConstPointer();
6178 const double *coo=_coords->getConstPointer();
6180 for(int i=0;i<nbOfCells;i++,pt++)
6182 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6185 case INTERP_KERNEL::NORM_QUAD4:
6187 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6188 *pt=INTERP_KERNEL::quadWarp(tmp);
6192 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6194 conn+=connI[i+1]-connI[i];
6196 ret->setName("Warp");
6197 ret->synchronizeTimeWithSupport();
6203 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6204 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6205 * treated: INTERP_KERNEL::NORM_QUAD4.
6206 * For a cell of other type an exception is thrown.
6207 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6208 * cells and one time, lying on \a this mesh. The caller is to delete this
6209 * field using decrRef() as it is no more needed.
6210 * \throw If the coordinates array is not set.
6211 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6212 * \throw If the connectivity data array has more than one component.
6213 * \throw If the connectivity data array has a named component.
6214 * \throw If the connectivity index data array has more than one component.
6215 * \throw If the connectivity index data array has a named component.
6216 * \throw If \a this->getMeshDimension() != 2.
6217 * \throw If \a this->getSpaceDimension() != 3.
6218 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6220 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6223 int spaceDim=getSpaceDimension();
6224 int meshDim=getMeshDimension();
6226 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6228 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6229 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6231 int nbOfCells=getNumberOfCells();
6232 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6233 arr->alloc(nbOfCells,1);
6234 double *pt=arr->getPointer();
6235 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6236 const int *conn=_nodal_connec->getConstPointer();
6237 const int *connI=_nodal_connec_index->getConstPointer();
6238 const double *coo=_coords->getConstPointer();
6240 for(int i=0;i<nbOfCells;i++,pt++)
6242 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6245 case INTERP_KERNEL::NORM_QUAD4:
6247 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6248 *pt=INTERP_KERNEL::quadSkew(tmp);
6252 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6254 conn+=connI[i+1]-connI[i];
6256 ret->setName("Skew");
6257 ret->synchronizeTimeWithSupport();
6262 * This method aggregate the bbox of each cell and put it into bbox parameter.
6264 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6265 * For all other cases this input parameter is ignored.
6266 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6268 * \throw If \a this is not fully set (coordinates and connectivity).
6269 * \throw If a cell in \a this has no valid nodeId.
6270 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6272 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6274 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6275 if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3)) // Compute refined boundary box for quadratic elements only in 2D.
6276 return getBoundingBoxForBBTreeFast();
6277 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6279 bool presenceOfQuadratic(false);
6280 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6282 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6283 if(cm.isQuadratic())
6284 presenceOfQuadratic=true;
6286 if(!presenceOfQuadratic)
6287 return getBoundingBoxForBBTreeFast();
6288 if(mDim==2 && sDim==2)
6289 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6291 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6293 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6297 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6298 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6300 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6302 * \throw If \a this is not fully set (coordinates and connectivity).
6303 * \throw If a cell in \a this has no valid nodeId.
6305 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6307 checkFullyDefined();
6308 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6309 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6310 double *bbox(ret->getPointer());
6311 for(int i=0;i<nbOfCells*spaceDim;i++)
6313 bbox[2*i]=std::numeric_limits<double>::max();
6314 bbox[2*i+1]=-std::numeric_limits<double>::max();
6316 const double *coordsPtr(_coords->getConstPointer());
6317 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6318 for(int i=0;i<nbOfCells;i++)
6320 int offset=connI[i]+1;
6321 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6322 for(int j=0;j<nbOfNodesForCell;j++)
6324 int nodeId=conn[offset+j];
6325 if(nodeId>=0 && nodeId<nbOfNodes)
6327 for(int k=0;k<spaceDim;k++)
6329 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6330 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6337 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6338 throw INTERP_KERNEL::Exception(oss.str().c_str());
6345 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6346 * useful for 2D meshes having quadratic cells
6347 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6348 * the two extremities of the arc of circle).
6350 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6351 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6352 * \throw If \a this is not fully defined.
6353 * \throw If \a this is not a mesh with meshDimension equal to 2.
6354 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6355 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6357 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6359 checkFullyDefined();
6360 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6361 if(spaceDim!=2 || spaceDim!=2)
6362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6363 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6364 double *bbox(ret->getPointer());
6365 const double *coords(_coords->getConstPointer());
6366 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6367 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6369 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6370 int sz(connI[1]-connI[0]-1);
6371 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6372 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6373 INTERP_KERNEL::QuadraticPolygon *pol(0);
6374 for(int j=0;j<sz;j++)
6376 int nodeId(conn[*connI+1+j]);
6377 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6379 if(!cm.isQuadratic())
6380 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6382 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6383 INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6384 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6390 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6391 * useful for 2D meshes having quadratic cells
6392 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6393 * the two extremities of the arc of circle).
6395 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6396 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6397 * \throw If \a this is not fully defined.
6398 * \throw If \a this is not a mesh with meshDimension equal to 1.
6399 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6400 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6402 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6404 checkFullyDefined();
6405 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6406 if(spaceDim!=2 || spaceDim!=2)
6407 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6408 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6409 double *bbox(ret->getPointer());
6410 const double *coords(_coords->getConstPointer());
6411 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6412 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6414 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6415 int sz(connI[1]-connI[0]-1);
6416 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6417 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6418 INTERP_KERNEL::Edge *edge(0);
6419 for(int j=0;j<sz;j++)
6421 int nodeId(conn[*connI+1+j]);
6422 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6424 if(!cm.isQuadratic())
6425 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6427 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6428 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6429 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6436 namespace ParaMEDMEMImpl
6441 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6442 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6451 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6452 bool operator() (const int& pos) { return _conn[pos]==_val; }
6462 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6463 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6464 * \a this is composed in cell types.
6465 * The returned array is of size 3*n where n is the number of different types present in \a this.
6466 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6467 * This parameter is kept only for compatibility with other methode listed above.
6469 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6471 checkConnectivityFullyDefined();
6472 const int *conn=_nodal_connec->getConstPointer();
6473 const int *connI=_nodal_connec_index->getConstPointer();
6474 const int *work=connI;
6475 int nbOfCells=getNumberOfCells();
6476 std::size_t n=getAllGeoTypes().size();
6477 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6478 std::set<INTERP_KERNEL::NormalizedCellType> types;
6479 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6481 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6482 if(types.find(typ)!=types.end())
6484 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6485 oss << " is not contiguous !";
6486 throw INTERP_KERNEL::Exception(oss.str().c_str());
6490 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6491 ret[3*i+1]=(int)std::distance(work,work2);
6498 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6499 * only for types cell, type node is not managed.
6500 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6501 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6502 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6503 * If 2 or more same geometric type is in \a code and exception is thrown too.
6505 * This method firstly checks
6506 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6507 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6508 * an exception is thrown too.
6510 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6511 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6512 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6514 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6518 std::size_t sz=code.size();
6521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6522 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6524 bool isNoPflUsed=true;
6525 for(std::size_t i=0;i<n;i++)
6526 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6528 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6530 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6531 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6532 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6535 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6538 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6539 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6540 if(types.size()==_types.size())
6543 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6545 int *retPtr=ret->getPointer();
6546 const int *connI=_nodal_connec_index->getConstPointer();
6547 const int *conn=_nodal_connec->getConstPointer();
6548 int nbOfCells=getNumberOfCells();
6551 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6553 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6554 int offset=(int)std::distance(connI,i);
6555 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6556 int nbOfCellsOfCurType=(int)std::distance(i,j);
6557 if(code[3*kk+2]==-1)
6558 for(int k=0;k<nbOfCellsOfCurType;k++)
6562 int idInIdsPerType=code[3*kk+2];
6563 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6565 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6568 zePfl->checkAllocated();
6569 if(zePfl->getNumberOfComponents()==1)
6571 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6573 if(*k>=0 && *k<nbOfCellsOfCurType)
6574 *retPtr=(*k)+offset;
6577 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6578 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6579 throw INTERP_KERNEL::Exception(oss.str().c_str());
6584 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6587 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6591 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6592 oss << " should be in [0," << idsPerType.size() << ") !";
6593 throw INTERP_KERNEL::Exception(oss.str().c_str());
6602 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6603 * 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.
6604 * 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.
6605 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6607 * \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.
6608 * \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,
6609 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6610 * \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.
6611 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6612 * \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
6614 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6617 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6618 if(profile->getNumberOfComponents()!=1)
6619 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6620 checkConnectivityFullyDefined();
6621 const int *conn=_nodal_connec->getConstPointer();
6622 const int *connI=_nodal_connec_index->getConstPointer();
6623 int nbOfCells=getNumberOfCells();
6624 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6625 std::vector<int> typeRangeVals(1);
6626 for(const int *i=connI;i!=connI+nbOfCells;)
6628 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6629 if(std::find(types.begin(),types.end(),curType)!=types.end())
6631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6633 types.push_back(curType);
6634 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6635 typeRangeVals.push_back((int)std::distance(connI,i));
6638 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6639 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6642 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6644 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6645 code.resize(3*nbOfCastsFinal);
6646 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6647 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6648 for(int i=0;i<nbOfCastsFinal;i++)
6650 int castId=castsPresent->getIJ(i,0);
6651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6652 idsInPflPerType2.push_back(tmp3);
6653 code[3*i]=(int)types[castId];
6654 code[3*i+1]=tmp3->getNumberOfTuples();
6655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6656 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6658 tmp4->copyStringInfoFrom(*profile);
6659 idsPerType2.push_back(tmp4);
6660 code[3*i+2]=(int)idsPerType2.size()-1;
6667 std::size_t sz2=idsInPflPerType2.size();
6668 idsInPflPerType.resize(sz2);
6669 for(std::size_t i=0;i<sz2;i++)
6671 DataArrayInt *locDa=idsInPflPerType2[i];
6673 idsInPflPerType[i]=locDa;
6675 std::size_t sz=idsPerType2.size();
6676 idsPerType.resize(sz);
6677 for(std::size_t i=0;i<sz;i++)
6679 DataArrayInt *locDa=idsPerType2[i];
6681 idsPerType[i]=locDa;
6686 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6687 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6688 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6689 * 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.
6691 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6693 checkFullyDefined();
6694 nM1LevMesh->checkFullyDefined();
6695 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6696 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6697 if(_coords!=nM1LevMesh->getCoords())
6698 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6701 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6702 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6703 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6704 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6705 tmp->setConnectivity(tmp0,tmp1);
6706 tmp->renumberCells(ret0->getConstPointer(),false);
6707 revDesc=tmp->getNodalConnectivity();
6708 revDescIndx=tmp->getNodalConnectivityIndex();
6709 DataArrayInt *ret=0;
6710 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6713 ret->getMaxValue(tmp2);
6715 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6716 throw INTERP_KERNEL::Exception(oss.str().c_str());
6721 revDescIndx->incrRef();
6724 meshnM1Old2New=ret0;
6729 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6730 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6731 * in "Old to New" mode.
6732 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6733 * this array using decrRef() as it is no more needed.
6734 * \throw If the nodal connectivity of cells is not defined.
6736 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6738 checkConnectivityFullyDefined();
6739 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6740 renumberCells(ret->getConstPointer(),false);
6745 * This methods checks that cells are sorted by their types.
6746 * This method makes asumption (no check) that connectivity is correctly set before calling.
6748 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6750 checkFullyDefined();
6751 const int *conn=_nodal_connec->getConstPointer();
6752 const int *connI=_nodal_connec_index->getConstPointer();
6753 int nbOfCells=getNumberOfCells();
6754 std::set<INTERP_KERNEL::NormalizedCellType> types;
6755 for(const int *i=connI;i!=connI+nbOfCells;)
6757 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6758 if(types.find(curType)!=types.end())
6760 types.insert(curType);
6761 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6767 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6768 * The geometric type order is specified by MED file.
6770 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6772 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6774 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6778 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6779 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6780 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6781 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6783 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6785 checkFullyDefined();
6786 const int *conn=_nodal_connec->getConstPointer();
6787 const int *connI=_nodal_connec_index->getConstPointer();
6788 int nbOfCells=getNumberOfCells();
6792 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6793 for(const int *i=connI;i!=connI+nbOfCells;)
6795 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6796 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6797 if(isTypeExists!=orderEnd)
6799 int pos=(int)std::distance(orderBg,isTypeExists);
6803 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6807 if(sg.find(curType)==sg.end())
6809 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6820 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6821 * 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
6822 * 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'.
6824 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6826 checkConnectivityFullyDefined();
6827 int nbOfCells=getNumberOfCells();
6828 const int *conn=_nodal_connec->getConstPointer();
6829 const int *connI=_nodal_connec_index->getConstPointer();
6830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6832 tmpa->alloc(nbOfCells,1);
6833 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6834 tmpb->fillWithZero();
6835 int *tmp=tmpa->getPointer();
6836 int *tmp2=tmpb->getPointer();
6837 for(const int *i=connI;i!=connI+nbOfCells;i++)
6839 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6842 int pos=(int)std::distance(orderBg,where);
6844 tmp[std::distance(connI,i)]=pos;
6848 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6849 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6850 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6851 throw INTERP_KERNEL::Exception(oss.str().c_str());
6854 nbPerType=tmpb.retn();
6859 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6861 * \return a new object containing the old to new correspondance.
6863 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6865 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6867 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6871 * 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.
6872 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6873 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6874 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6876 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6878 DataArrayInt *nbPerType=0;
6879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6880 nbPerType->decrRef();
6881 return tmpa->buildPermArrPerLevel();
6885 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6886 * The number of cells remains unchanged after the call of this method.
6887 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6888 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6890 * \return the array giving the correspondance old to new.
6892 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6894 checkFullyDefined();
6896 const int *conn=_nodal_connec->getConstPointer();
6897 const int *connI=_nodal_connec_index->getConstPointer();
6898 int nbOfCells=getNumberOfCells();
6899 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6900 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6901 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6903 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6904 types.push_back(curType);
6905 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6907 DataArrayInt *ret=DataArrayInt::New();
6908 ret->alloc(nbOfCells,1);
6909 int *retPtr=ret->getPointer();
6910 std::fill(retPtr,retPtr+nbOfCells,-1);
6912 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6914 for(const int *i=connI;i!=connI+nbOfCells;i++)
6915 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6916 retPtr[std::distance(connI,i)]=newCellId++;
6918 renumberCells(retPtr,false);
6923 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6924 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6925 * This method makes asumption that connectivity is correctly set before calling.
6927 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6929 checkConnectivityFullyDefined();
6930 const int *conn=_nodal_connec->getConstPointer();
6931 const int *connI=_nodal_connec_index->getConstPointer();
6932 int nbOfCells=getNumberOfCells();
6933 std::vector<MEDCouplingUMesh *> ret;
6934 for(const int *i=connI;i!=connI+nbOfCells;)
6936 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6937 int beginCellId=(int)std::distance(connI,i);
6938 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6939 int endCellId=(int)std::distance(connI,i);
6940 int sz=endCellId-beginCellId;
6941 int *cells=new int[sz];
6942 for(int j=0;j<sz;j++)
6943 cells[j]=beginCellId+j;
6944 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6952 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6953 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6954 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6956 * \return a newly allocated instance, that the caller must manage.
6957 * \throw If \a this contains more than one geometric type.
6958 * \throw If the nodal connectivity of \a this is not fully defined.
6959 * \throw If the internal data is not coherent.
6961 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6963 checkConnectivityFullyDefined();
6964 if(_types.size()!=1)
6965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6966 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6967 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6968 ret->setCoords(getCoords());
6969 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6973 retC->setNodalConnectivity(c);
6977 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6979 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6980 DataArrayInt *c=0,*ci=0;
6981 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6983 retD->setNodalConnectivity(cs,cis);
6988 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6990 checkConnectivityFullyDefined();
6991 if(_types.size()!=1)
6992 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6993 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6994 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6997 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6998 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6999 throw INTERP_KERNEL::Exception(oss.str().c_str());
7001 int nbCells=getNumberOfCells();
7003 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7004 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7005 int *outPtr=connOut->getPointer();
7006 const int *conn=_nodal_connec->begin();
7007 const int *connI=_nodal_connec_index->begin();
7009 for(int i=0;i<nbCells;i++,connI++)
7011 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7012 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7015 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 << ") !";
7016 throw INTERP_KERNEL::Exception(oss.str().c_str());
7019 return connOut.retn();
7022 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7024 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7025 checkConnectivityFullyDefined();
7026 if(_types.size()!=1)
7027 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7028 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7030 throw INTERP_KERNEL::Exception(msg0);
7031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7032 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7033 int *cp(c->getPointer()),*cip(ci->getPointer());
7034 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7036 for(int i=0;i<nbCells;i++,cip++,incip++)
7038 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7039 int delta(stop-strt);
7042 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7043 cp=std::copy(incp+strt,incp+stop,cp);
7045 throw INTERP_KERNEL::Exception(msg0);
7048 throw INTERP_KERNEL::Exception(msg0);
7049 cip[1]=cip[0]+delta;
7051 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7055 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7056 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7057 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7058 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7059 * are not used here to avoid the build of big permutation array.
7061 * \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
7062 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7063 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7064 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7065 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7066 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7067 * \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
7068 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7070 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7071 DataArrayInt *&szOfCellGrpOfSameType,
7072 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7074 std::vector<const MEDCouplingUMesh *> ms2;
7075 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7078 (*it)->checkConnectivityFullyDefined();
7082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7083 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7084 int meshDim=ms2[0]->getMeshDimension();
7085 std::vector<const MEDCouplingUMesh *> m1ssm;
7086 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7088 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7089 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7091 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7092 ret1->alloc(0,1); ret2->alloc(0,1);
7093 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7095 if(meshDim!=(*it)->getMeshDimension())
7096 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7097 if(refCoo!=(*it)->getCoords())
7098 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7099 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7100 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7101 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7102 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7104 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7105 m1ssmSingleAuto.push_back(singleCell);
7106 m1ssmSingle.push_back(singleCell);
7107 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7110 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7112 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7113 for(std::size_t i=0;i<m1ssm.size();i++)
7114 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7115 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7116 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7117 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7122 * This method returns a newly created DataArrayInt instance.
7123 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7125 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7127 checkFullyDefined();
7128 const int *conn=_nodal_connec->getConstPointer();
7129 const int *connIndex=_nodal_connec_index->getConstPointer();
7130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7131 for(const int *w=begin;w!=end;w++)
7132 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7133 ret->pushBackSilent(*w);
7138 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7139 * are in [0:getNumberOfCells())
7141 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7143 checkFullyDefined();
7144 const int *conn=_nodal_connec->getConstPointer();
7145 const int *connI=_nodal_connec_index->getConstPointer();
7146 int nbOfCells=getNumberOfCells();
7147 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7148 int *tmp=new int[nbOfCells];
7149 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7152 for(const int *i=connI;i!=connI+nbOfCells;i++)
7153 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7154 tmp[std::distance(connI,i)]=j++;
7156 DataArrayInt *ret=DataArrayInt::New();
7157 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7158 ret->copyStringInfoFrom(*da);
7159 int *retPtr=ret->getPointer();
7160 const int *daPtr=da->getConstPointer();
7161 int nbOfElems=da->getNbOfElems();
7162 for(int k=0;k<nbOfElems;k++)
7163 retPtr[k]=tmp[daPtr[k]];
7169 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7170 * This method \b works \b for mesh sorted by type.
7171 * cells whose ids is in 'idsPerGeoType' array.
7172 * This method conserves coords and name of mesh.
7174 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7176 std::vector<int> code=getDistributionOfTypes();
7177 std::size_t nOfTypesInThis=code.size()/3;
7178 int sz=0,szOfType=0;
7179 for(std::size_t i=0;i<nOfTypesInThis;i++)
7184 szOfType=code[3*i+1];
7186 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7187 if(*work<0 || *work>=szOfType)
7189 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7190 oss << ". It should be in [0," << szOfType << ") !";
7191 throw INTERP_KERNEL::Exception(oss.str().c_str());
7193 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7194 int *idsPtr=idsTokeep->getPointer();
7196 for(std::size_t i=0;i<nOfTypesInThis;i++)
7199 for(int j=0;j<code[3*i+1];j++)
7202 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7203 offset+=code[3*i+1];
7205 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7206 ret->copyTinyInfoFrom(this);
7211 * This method returns a vector of size 'this->getNumberOfCells()'.
7212 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7214 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7216 int ncell=getNumberOfCells();
7217 std::vector<bool> ret(ncell);
7218 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7219 const int *c=getNodalConnectivity()->getConstPointer();
7220 for(int i=0;i<ncell;i++)
7222 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7223 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7224 ret[i]=cm.isQuadratic();
7230 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7232 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7234 if(other->getType()!=UNSTRUCTURED)
7235 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7236 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7237 return MergeUMeshes(this,otherC);
7241 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7242 * computed by averaging coordinates of cell nodes, so this method is not a right
7243 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7244 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7245 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7246 * components. The caller is to delete this array using decrRef() as it is
7248 * \throw If the coordinates array is not set.
7249 * \throw If the nodal connectivity of cells is not defined.
7250 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7252 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7254 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7255 int spaceDim=getSpaceDimension();
7256 int nbOfCells=getNumberOfCells();
7257 ret->alloc(nbOfCells,spaceDim);
7258 ret->copyStringInfoFrom(*getCoords());
7259 double *ptToFill=ret->getPointer();
7260 const int *nodal=_nodal_connec->getConstPointer();
7261 const int *nodalI=_nodal_connec_index->getConstPointer();
7262 const double *coor=_coords->getConstPointer();
7263 for(int i=0;i<nbOfCells;i++)
7265 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7266 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7273 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7274 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7276 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7277 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7279 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7280 * \throw If \a this is not fully defined (coordinates and connectivity)
7281 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7283 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7285 checkFullyDefined();
7286 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7287 int spaceDim=getSpaceDimension();
7288 int nbOfCells=getNumberOfCells();
7289 int nbOfNodes=getNumberOfNodes();
7290 ret->alloc(nbOfCells,spaceDim);
7291 double *ptToFill=ret->getPointer();
7292 const int *nodal=_nodal_connec->getConstPointer();
7293 const int *nodalI=_nodal_connec_index->getConstPointer();
7294 const double *coor=_coords->getConstPointer();
7295 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7297 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7298 std::fill(ptToFill,ptToFill+spaceDim,0.);
7299 if(type!=INTERP_KERNEL::NORM_POLYHED)
7301 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7303 if(*conn>=0 && *conn<nbOfNodes)
7304 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7307 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7308 throw INTERP_KERNEL::Exception(oss.str().c_str());
7311 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7312 if(nbOfNodesInCell>0)
7313 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7316 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7317 throw INTERP_KERNEL::Exception(oss.str().c_str());
7322 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7324 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7326 if(*it>=0 && *it<nbOfNodes)
7327 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7330 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7331 throw INTERP_KERNEL::Exception(oss.str().c_str());
7335 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7338 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7339 throw INTERP_KERNEL::Exception(oss.str().c_str());
7347 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7348 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7349 * are specified via an array of cell ids.
7350 * \warning Validity of the specified cell ids is not checked!
7351 * Valid range is [ 0, \a this->getNumberOfCells() ).
7352 * \param [in] begin - an array of cell ids of interest.
7353 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7354 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7355 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7356 * caller is to delete this array using decrRef() as it is no more needed.
7357 * \throw If the coordinates array is not set.
7358 * \throw If the nodal connectivity of cells is not defined.
7360 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7361 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7363 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7365 DataArrayDouble *ret=DataArrayDouble::New();
7366 int spaceDim=getSpaceDimension();
7367 int nbOfTuple=(int)std::distance(begin,end);
7368 ret->alloc(nbOfTuple,spaceDim);
7369 double *ptToFill=ret->getPointer();
7370 double *tmp=new double[spaceDim];
7371 const int *nodal=_nodal_connec->getConstPointer();
7372 const int *nodalI=_nodal_connec_index->getConstPointer();
7373 const double *coor=_coords->getConstPointer();
7374 for(const int *w=begin;w!=end;w++)
7376 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7377 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7385 * 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".
7386 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7387 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7388 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7389 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7391 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7392 * \throw If spaceDim!=3 or meshDim!=2.
7393 * \throw If connectivity of \a this is invalid.
7394 * \throw If connectivity of a cell in \a this points to an invalid node.
7396 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7398 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7399 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7400 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7401 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7402 ret->alloc(nbOfCells,4);
7403 double *retPtr(ret->getPointer());
7404 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7405 const double *coor(_coords->begin());
7406 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7408 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7409 if(nodalI[1]-nodalI[0]>=3)
7411 for(int j=0;j<3;j++)
7413 int nodeId(nodal[nodalI[0]+1+j]);
7414 if(nodeId>=0 && nodeId<nbOfNodes)
7415 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7418 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7419 throw INTERP_KERNEL::Exception(oss.str().c_str());
7425 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7426 throw INTERP_KERNEL::Exception(oss.str().c_str());
7428 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7429 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7435 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7438 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7441 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7442 da->checkAllocated();
7443 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7445 int nbOfTuples=da->getNumberOfTuples();
7446 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7447 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7448 c->alloc(2*nbOfTuples,1);
7449 cI->alloc(nbOfTuples+1,1);
7450 int *cp=c->getPointer();
7451 int *cip=cI->getPointer();
7453 for(int i=0;i<nbOfTuples;i++)
7455 *cp++=INTERP_KERNEL::NORM_POINT1;
7459 ret->setConnectivity(c,cI,true);
7463 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7464 * Cells and nodes of
7465 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7466 * \param [in] mesh1 - the first mesh.
7467 * \param [in] mesh2 - the second mesh.
7468 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7469 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7470 * is no more needed.
7471 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7472 * \throw If the coordinates array is not set in none of the meshes.
7473 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7474 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7476 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7478 std::vector<const MEDCouplingUMesh *> tmp(2);
7479 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7480 return MergeUMeshes(tmp);
7484 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7485 * Cells and nodes of
7486 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7487 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7488 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7489 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7490 * is no more needed.
7491 * \throw If \a a.size() == 0.
7492 * \throw If \a a[ *i* ] == NULL.
7493 * \throw If the coordinates array is not set in none of the meshes.
7494 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7495 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7497 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7499 std::size_t sz=a.size();
7501 return MergeUMeshesLL(a);
7502 for(std::size_t ii=0;ii<sz;ii++)
7505 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7506 throw INTERP_KERNEL::Exception(oss.str().c_str());
7508 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7509 std::vector< const MEDCouplingUMesh * > aa(sz);
7511 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7513 const MEDCouplingUMesh *cur=a[i];
7514 const DataArrayDouble *coo=cur->getCoords();
7516 spaceDim=coo->getNumberOfComponents();
7519 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7520 for(std::size_t i=0;i<sz;i++)
7522 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7525 return MergeUMeshesLL(aa);
7530 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7534 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7535 int meshDim=(*it)->getMeshDimension();
7536 int nbOfCells=(*it)->getNumberOfCells();
7537 int meshLgth=(*it++)->getMeshLength();
7538 for(;it!=a.end();it++)
7540 if(meshDim!=(*it)->getMeshDimension())
7541 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7542 nbOfCells+=(*it)->getNumberOfCells();
7543 meshLgth+=(*it)->getMeshLength();
7545 std::vector<const MEDCouplingPointSet *> aps(a.size());
7546 std::copy(a.begin(),a.end(),aps.begin());
7547 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7548 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7549 ret->setCoords(pts);
7550 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7551 c->alloc(meshLgth,1);
7552 int *cPtr=c->getPointer();
7553 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7554 cI->alloc(nbOfCells+1,1);
7555 int *cIPtr=cI->getPointer();
7559 for(it=a.begin();it!=a.end();it++)
7561 int curNbOfCell=(*it)->getNumberOfCells();
7562 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7563 const int *curC=(*it)->_nodal_connec->getConstPointer();
7564 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7565 for(int j=0;j<curNbOfCell;j++)
7567 const int *src=curC+curCI[j];
7569 for(;src!=curC+curCI[j+1];src++,cPtr++)
7577 offset+=curCI[curNbOfCell];
7578 offset2+=(*it)->getNumberOfNodes();
7581 ret->setConnectivity(c,cI,true);
7588 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7589 * dimension and sharing the node coordinates array.
7590 * All cells of the first mesh precede all cells of the second mesh
7591 * within the result mesh.
7592 * \param [in] mesh1 - the first mesh.
7593 * \param [in] mesh2 - the second mesh.
7594 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7595 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7596 * is no more needed.
7597 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7598 * \throw If the meshes do not share the node coordinates array.
7599 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7600 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7602 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7604 std::vector<const MEDCouplingUMesh *> tmp(2);
7605 tmp[0]=mesh1; tmp[1]=mesh2;
7606 return MergeUMeshesOnSameCoords(tmp);
7610 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7611 * dimension and sharing the node coordinates array.
7612 * All cells of the *i*-th mesh precede all cells of the
7613 * (*i*+1)-th mesh within the result mesh.
7614 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7615 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7616 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7617 * is no more needed.
7618 * \throw If \a a.size() == 0.
7619 * \throw If \a a[ *i* ] == NULL.
7620 * \throw If the meshes do not share the node coordinates array.
7621 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7622 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7624 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7627 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7628 for(std::size_t ii=0;ii<meshes.size();ii++)
7631 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7632 throw INTERP_KERNEL::Exception(oss.str().c_str());
7634 const DataArrayDouble *coords=meshes.front()->getCoords();
7635 int meshDim=meshes.front()->getMeshDimension();
7636 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7638 int meshIndexLgth=0;
7639 for(;iter!=meshes.end();iter++)
7641 if(coords!=(*iter)->getCoords())
7642 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7643 if(meshDim!=(*iter)->getMeshDimension())
7644 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7645 meshLgth+=(*iter)->getMeshLength();
7646 meshIndexLgth+=(*iter)->getNumberOfCells();
7648 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7649 nodal->alloc(meshLgth,1);
7650 int *nodalPtr=nodal->getPointer();
7651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7652 nodalIndex->alloc(meshIndexLgth+1,1);
7653 int *nodalIndexPtr=nodalIndex->getPointer();
7655 for(iter=meshes.begin();iter!=meshes.end();iter++)
7657 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7658 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7659 int nbOfCells=(*iter)->getNumberOfCells();
7660 int meshLgth2=(*iter)->getMeshLength();
7661 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7662 if(iter!=meshes.begin())
7663 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7665 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7668 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7669 ret->setName("merge");
7670 ret->setMeshDimension(meshDim);
7671 ret->setConnectivity(nodal,nodalIndex,true);
7672 ret->setCoords(coords);
7677 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7678 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7679 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7680 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7681 * New" mode are returned for each input mesh.
7682 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7683 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7684 * valid values [0,1,2], see zipConnectivityTraducer().
7685 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7686 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7687 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7689 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7690 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7691 * is no more needed.
7692 * \throw If \a meshes.size() == 0.
7693 * \throw If \a meshes[ *i* ] == NULL.
7694 * \throw If the meshes do not share the node coordinates array.
7695 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7696 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7697 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7698 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7700 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7702 //All checks are delegated to MergeUMeshesOnSameCoords
7703 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7705 corr.resize(meshes.size());
7706 std::size_t nbOfMeshes=meshes.size();
7708 const int *o2nPtr=o2n->getConstPointer();
7709 for(std::size_t i=0;i<nbOfMeshes;i++)
7711 DataArrayInt *tmp=DataArrayInt::New();
7712 int curNbOfCells=meshes[i]->getNumberOfCells();
7713 tmp->alloc(curNbOfCells,1);
7714 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7715 offset+=curNbOfCells;
7716 tmp->setName(meshes[i]->getName());
7723 * Makes all given meshes share the nodal connectivity array. The common connectivity
7724 * array is created by concatenating the connectivity arrays of all given meshes. All
7725 * the given meshes must be of the same space dimension but dimension of cells **can
7726 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7727 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7728 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7729 * \param [in,out] meshes - a vector of meshes to update.
7730 * \throw If any of \a meshes is NULL.
7731 * \throw If the coordinates array is not set in any of \a meshes.
7732 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7733 * \throw If \a meshes are of different space dimension.
7735 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7737 std::size_t sz=meshes.size();
7740 std::vector< const DataArrayDouble * > coords(meshes.size());
7741 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7742 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7746 (*it)->checkConnectivityFullyDefined();
7747 const DataArrayDouble *coo=(*it)->getCoords();
7752 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7753 oss << " has no coordinate array defined !";
7754 throw INTERP_KERNEL::Exception(oss.str().c_str());
7759 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7760 oss << " is null !";
7761 throw INTERP_KERNEL::Exception(oss.str().c_str());
7764 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7765 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7766 int offset=(*it)->getNumberOfNodes();
7767 (*it++)->setCoords(res);
7768 for(;it!=meshes.end();it++)
7770 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7771 (*it)->setCoords(res);
7772 (*it)->shiftNodeNumbersInConn(offset);
7773 offset+=oldNumberOfNodes;
7778 * Merges nodes coincident with a given precision within all given meshes that share
7779 * the nodal connectivity array. The given meshes **can be of different** mesh
7780 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7781 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7782 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7783 * \param [in,out] meshes - a vector of meshes to update.
7784 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7785 * \throw If any of \a meshes is NULL.
7786 * \throw If the \a meshes do not share the same node coordinates array.
7787 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7789 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7793 std::set<const DataArrayDouble *> s;
7794 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7797 s.insert((*it)->getCoords());
7800 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 !";
7801 throw INTERP_KERNEL::Exception(oss.str().c_str());
7806 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 !";
7807 throw INTERP_KERNEL::Exception(oss.str().c_str());
7809 const DataArrayDouble *coo=*(s.begin());
7813 DataArrayInt *comm,*commI;
7814 coo->findCommonTuples(eps,-1,comm,commI);
7815 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7816 int oldNbOfNodes=coo->getNumberOfTuples();
7818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7819 if(oldNbOfNodes==newNbOfNodes)
7821 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7822 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7824 (*it)->renumberNodesInConn(o2n->getConstPointer());
7825 (*it)->setCoords(newCoords);
7830 * 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.
7831 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7832 * \param isQuad specifies the policy of connectivity.
7833 * @ret in/out parameter in which the result will be append
7835 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7837 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7838 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7839 ret.push_back(cm.getExtrudedType());
7840 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7843 case INTERP_KERNEL::NORM_POINT1:
7845 ret.push_back(connBg[1]);
7846 ret.push_back(connBg[1]+nbOfNodesPerLev);
7849 case INTERP_KERNEL::NORM_SEG2:
7851 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7852 ret.insert(ret.end(),conn,conn+4);
7855 case INTERP_KERNEL::NORM_SEG3:
7857 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7858 ret.insert(ret.end(),conn,conn+8);
7861 case INTERP_KERNEL::NORM_QUAD4:
7863 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7864 ret.insert(ret.end(),conn,conn+8);
7867 case INTERP_KERNEL::NORM_TRI3:
7869 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7870 ret.insert(ret.end(),conn,conn+6);
7873 case INTERP_KERNEL::NORM_TRI6:
7875 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,
7876 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7877 ret.insert(ret.end(),conn,conn+15);
7880 case INTERP_KERNEL::NORM_QUAD8:
7883 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7884 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7885 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7887 ret.insert(ret.end(),conn,conn+20);
7890 case INTERP_KERNEL::NORM_POLYGON:
7892 std::back_insert_iterator< std::vector<int> > ii(ret);
7893 std::copy(connBg+1,connEnd,ii);
7895 std::reverse_iterator<const int *> rConnBg(connEnd);
7896 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7897 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7898 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7899 for(std::size_t i=0;i<nbOfRadFaces;i++)
7902 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7903 std::copy(conn,conn+4,ii);
7908 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7913 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7915 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7918 double v[3]={0.,0.,0.};
7919 std::size_t sz=std::distance(begin,end);
7924 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];
7925 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7926 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7928 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7930 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
7931 // SEG3 forming a circle):
7932 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
7934 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
7935 for(std::size_t j=0;j<sz;j++)
7937 if (j%2) // current point i is quadratic, next point i+1 is standard
7940 ip1 = (j+1)%sz; // ip1 = "i+1"
7942 else // current point i is standard, next point i+1 is quadratic
7947 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7948 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7949 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7951 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7957 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7959 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7961 std::vector<std::pair<int,int> > edges;
7962 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7963 const int *bgFace=begin;
7964 for(std::size_t i=0;i<nbOfFaces;i++)
7966 const int *endFace=std::find(bgFace+1,end,-1);
7967 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7968 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7970 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7971 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7973 edges.push_back(p1);
7977 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7981 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7983 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7985 double vec0[3],vec1[3];
7986 std::size_t sz=std::distance(begin,end);
7988 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7989 int nbOfNodes=(int)sz/2;
7990 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7991 const double *pt0=coords+3*begin[0];
7992 const double *pt1=coords+3*begin[nbOfNodes];
7993 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7994 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7997 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7999 std::size_t sz=std::distance(begin,end);
8000 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8001 std::size_t nbOfNodes(sz/2);
8002 std::copy(begin,end,(int *)tmp);
8003 for(std::size_t j=1;j<nbOfNodes;j++)
8005 begin[j]=tmp[nbOfNodes-j];
8006 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8010 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8012 std::size_t sz=std::distance(begin,end);
8014 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8015 double vec0[3],vec1[3];
8016 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8017 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];
8018 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;
8021 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8023 std::size_t sz=std::distance(begin,end);
8025 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8027 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8028 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8029 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8033 * 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 )
8034 * 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
8037 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8038 * \param [in] coords the coordinates with nb of components exactly equal to 3
8039 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8040 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8041 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8043 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8045 int nbFaces=std::count(begin+1,end,-1)+1;
8046 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8047 double *vPtr=v->getPointer();
8048 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8049 double *pPtr=p->getPointer();
8050 const int *stFaceConn=begin+1;
8051 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8053 const int *endFaceConn=std::find(stFaceConn,end,-1);
8054 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8055 stFaceConn=endFaceConn+1;
8057 pPtr=p->getPointer(); vPtr=v->getPointer();
8058 DataArrayInt *comm1=0,*commI1=0;
8059 v->findCommonTuples(eps,-1,comm1,commI1);
8060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8061 const int *comm1Ptr=comm1->getConstPointer();
8062 const int *commI1Ptr=commI1->getConstPointer();
8063 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8064 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8066 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8067 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8068 mm->finishInsertingCells();
8070 for(int i=0;i<nbOfGrps1;i++)
8072 int vecId=comm1Ptr[commI1Ptr[i]];
8073 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8074 DataArrayInt *comm2=0,*commI2=0;
8075 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8077 const int *comm2Ptr=comm2->getConstPointer();
8078 const int *commI2Ptr=commI2->getConstPointer();
8079 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8080 for(int j=0;j<nbOfGrps2;j++)
8082 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8084 res->insertAtTheEnd(begin,end);
8085 res->pushBackSilent(-1);
8089 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8091 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8092 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8093 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8094 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8097 const int *idsNodePtr=idsNode->getConstPointer();
8098 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];
8099 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8100 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8101 if(std::abs(norm)>eps)
8103 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8104 mm3->rotate(center,vec,angle);
8106 mm3->changeSpaceDimension(2);
8107 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8108 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8109 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8110 int nbOfCells=mm4->getNumberOfCells();
8111 for(int k=0;k<nbOfCells;k++)
8114 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8115 res->pushBackSilent(idsNodePtr[*work]);
8116 res->pushBackSilent(-1);
8121 res->popBackSilent();
8125 * 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
8126 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8128 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8129 * \param [in] coords coordinates expected to have 3 components.
8130 * \param [in] begin start of the nodal connectivity of the face.
8131 * \param [in] end end of the nodal connectivity (excluded) of the face.
8132 * \param [out] v the normalized vector of size 3
8133 * \param [out] p the pos of plane
8135 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8137 std::size_t nbPoints=std::distance(begin,end);
8139 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8140 double vec[3]={0.,0.,0.};
8142 bool refFound=false;
8143 for(;j<nbPoints-1 && !refFound;j++)
8145 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8146 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8147 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8148 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8152 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8155 for(std::size_t i=j;i<nbPoints-1;i++)
8158 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8159 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8160 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8161 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8164 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8165 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];
8166 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8169 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8170 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8174 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8178 * This method tries to obtain a well oriented polyhedron.
8179 * If the algorithm fails, an exception will be thrown.
8181 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8183 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8184 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8185 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8187 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8188 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8189 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8191 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8194 std::size_t smthChanged=0;
8195 for(std::size_t i=0;i<nbOfFaces;i++)
8197 endFace=std::find(bgFace+1,end,-1);
8198 nbOfEdgesInFace=std::distance(bgFace,endFace);
8202 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8204 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8205 std::pair<int,int> p2(p1.second,p1.first);
8206 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8207 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8208 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8213 std::reverse(bgFace+1,endFace);
8214 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8216 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8217 std::pair<int,int> p2(p1.second,p1.first);
8218 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8219 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8220 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8221 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8222 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8223 if(it!=edgesOK.end())
8226 edgesFinished.push_back(p1);
8229 edgesOK.push_back(p1);
8236 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8238 if(!edgesOK.empty())
8239 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8240 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8241 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8243 for(std::size_t i=0;i<nbOfFaces;i++)
8245 endFace=std::find(bgFace+1,end,-1);
8246 std::reverse(bgFace+1,endFace);
8253 * This method makes the assumption spacedimension == meshdimension == 2.
8254 * This method works only for linear cells.
8256 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8258 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8260 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8261 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8262 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8264 int nbOfNodesExpected=m->getNumberOfNodes();
8265 if(m->getNumberOfCells()!=nbOfNodesExpected)
8266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8268 const int *n2oPtr=n2o->getConstPointer();
8269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8270 m->getReverseNodalConnectivity(revNodal,revNodalI);
8271 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8272 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8273 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8275 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
8276 if(nbOfNodesExpected<1)
8279 int prevNode=nodalPtr[nodalIPtr[0]+1];
8280 *work++=n2oPtr[prevNode];
8281 for(int i=1;i<nbOfNodesExpected;i++)
8283 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8285 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8286 conn.erase(prevNode);
8289 int curNode=*(conn.begin());
8290 *work++=n2oPtr[curNode];
8291 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8292 shar.erase(prevCell);
8295 prevCell=*(shar.begin());
8299 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8302 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8305 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8311 * This method makes the assumption spacedimension == meshdimension == 3.
8312 * This method works only for linear cells.
8314 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8316 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8318 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8320 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8321 const int *conn=m->getNodalConnectivity()->getConstPointer();
8322 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8323 int nbOfCells=m->getNumberOfCells();
8324 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8325 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8328 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8329 for(int i=1;i<nbOfCells;i++)
8332 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8338 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8339 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8341 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8345 for(int i=0;i<nbOfNodesInCell;i++)
8346 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8347 else if(spaceDim==2)
8349 for(int i=0;i<nbOfNodesInCell;i++)
8351 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8356 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8359 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8361 int nbOfCells=getNumberOfCells();
8363 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8364 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};
8365 ofs << " <" << getVTKDataSetType() << ">\n";
8366 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8367 ofs << " <PointData>\n" << pointData << std::endl;
8368 ofs << " </PointData>\n";
8369 ofs << " <CellData>\n" << cellData << std::endl;
8370 ofs << " </CellData>\n";
8371 ofs << " <Points>\n";
8372 if(getSpaceDimension()==3)
8373 _coords->writeVTK(ofs,8,"Points",byteData);
8376 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8377 coo->writeVTK(ofs,8,"Points",byteData);
8379 ofs << " </Points>\n";
8380 ofs << " <Cells>\n";
8381 const int *cPtr=_nodal_connec->getConstPointer();
8382 const int *cIPtr=_nodal_connec_index->getConstPointer();
8383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8387 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8388 int szFaceOffsets=0,szConn=0;
8389 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8392 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8395 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8396 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8400 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8401 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8402 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8403 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8404 w4=std::copy(c.begin(),c.end(),w4);
8407 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8408 types->writeVTK(ofs,8,"UInt8","types",byteData);
8409 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8410 if(szFaceOffsets!=0)
8411 {//presence of Polyhedra
8412 connectivity->reAlloc(szConn);
8413 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8414 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8415 w1=faces->getPointer();
8416 for(int i=0;i<nbOfCells;i++)
8417 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8419 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8421 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8422 for(int j=0;j<nbFaces;j++)
8424 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8425 *w1++=(int)std::distance(w6,w5);
8426 w1=std::copy(w6,w5,w1);
8430 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8432 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8433 ofs << " </Cells>\n";
8434 ofs << " </Piece>\n";
8435 ofs << " </" << getVTKDataSetType() << ">\n";
8438 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8440 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8442 { stream << " Not set !"; return ; }
8443 stream << " Mesh dimension : " << _mesh_dim << ".";
8447 { stream << " No coordinates set !"; return ; }
8448 if(!_coords->isAllocated())
8449 { stream << " Coordinates set but not allocated !"; return ; }
8450 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8451 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8452 if(!_nodal_connec_index)
8453 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8454 if(!_nodal_connec_index->isAllocated())
8455 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8456 int lgth=_nodal_connec_index->getNumberOfTuples();
8457 int cpt=_nodal_connec_index->getNumberOfComponents();
8458 if(cpt!=1 || lgth<1)
8460 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8463 std::string MEDCouplingUMesh::getVTKDataSetType() const
8465 return std::string("UnstructuredGrid");
8469 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8470 * returns a result mesh constituted by polygons.
8471 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8472 * all nodes from m2.
8473 * The meshes should be in 2D space. In
8474 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8476 * \param [in] m1 - the first input mesh which is a partitioned object.
8477 * \param [in] m2 - the second input mesh which is a partition tool.
8478 * \param [in] eps - precision used to detect coincident mesh entities.
8479 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8480 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8481 * this array using decrRef() as it is no more needed.
8482 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8483 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8484 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8485 * any cell of \a m2. The caller is to delete this array using decrRef() as
8486 * it is no more needed.
8487 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8488 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8489 * is no more needed.
8490 * \throw If the coordinates array is not set in any of the meshes.
8491 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8492 * \throw If any of the meshes is not a 2D mesh in 2D space.
8494 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8495 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8497 m1->checkFullyDefined();
8498 m2->checkFullyDefined();
8499 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8500 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8502 // Step 1: compute all edge intersections (new nodes)
8503 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8504 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8505 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8506 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8507 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8508 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8509 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8510 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8511 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8512 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8514 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8516 // Step 2: re-order newly created nodes according to the ordering found in m2
8517 std::vector< std::vector<int> > intersectEdge2;
8518 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8519 subDiv2.clear(); dd5=0; dd6=0;
8522 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8523 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8524 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8525 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8527 // Step 4: Prepare final result:
8528 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8529 addCooDa->alloc((int)(addCoo.size())/2,2);
8530 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8531 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8532 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8533 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8534 std::vector<const DataArrayDouble *> coordss(4);
8535 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8536 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8537 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8541 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8542 ret->setConnectivity(conn,connI,true);
8543 ret->setCoords(coo);
8544 cellNb1=c1.retn(); cellNb2=c2.retn();
8550 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8551 * (newly created) nodes corresponding to the edge intersections.
8553 * @param[out] cr, crI connectivity of the resulting mesh
8554 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8555 * TODO: describe input parameters
8557 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8558 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8559 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8560 const std::vector<double>& addCoords,
8561 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8563 static const int SPACEDIM=2;
8564 const double *coo1=m1->getCoords()->getConstPointer();
8565 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8566 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8567 int offset1=m1->getNumberOfNodes();
8568 const double *coo2=m2->getCoords()->getConstPointer();
8569 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8570 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8571 int offset2=offset1+m2->getNumberOfNodes();
8572 int offset3=offset2+((int)addCoords.size())/2;
8573 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8574 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8575 // Here a BBTree on 2D-cells, not on segments:
8576 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8577 int ncell1=m1->getNumberOfCells();
8579 for(int i=0;i<ncell1;i++)
8581 std::vector<int> candidates2;
8582 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8583 std::map<INTERP_KERNEL::Node *,int> mapp;
8584 std::map<int,INTERP_KERNEL::Node *> mappRev;
8585 INTERP_KERNEL::QuadraticPolygon pol1;
8586 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8587 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8588 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8589 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8590 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8591 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8592 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8594 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
8595 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8596 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8597 for(it1.first();!it1.finished();it1.next())
8598 edges1.insert(it1.current()->getPtr());
8600 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8601 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8603 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8605 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8606 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8607 // Complete mapping with elements coming from the current cell it2 in mesh2:
8608 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8609 // pol2 is the new QP in the final merged result.
8610 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8611 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8614 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8616 pol1.initLocationsWithOther(pol2s[ii]);
8617 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8618 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8619 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8621 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8622 // by m2 but that we still want to keep in the final result.
8627 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8629 catch(INTERP_KERNEL::Exception& e)
8631 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();
8632 throw INTERP_KERNEL::Exception(oss.str().c_str());
8635 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8636 (*it).second->decrRef();
8641 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8642 * It builds the descending connectivity of the two meshes, and then using a binary tree
8643 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8644 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8646 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8647 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8648 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8649 std::vector<double>& addCoo,
8650 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8651 throw(INTERP_KERNEL::Exception)
8653 static const int SPACEDIM=2;
8654 // Build desc connectivity
8655 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8656 desc2=DataArrayInt::New();
8657 descIndx2=DataArrayInt::New();
8658 revDesc2=DataArrayInt::New();
8659 revDescIndx2=DataArrayInt::New();
8660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8662 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8663 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8664 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8665 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8666 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8668 // Build BB tree of all edges in the tool mesh (second mesh)
8669 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8670 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8671 int nDescCell1=m1Desc->getNumberOfCells();
8672 int nDescCell2=m2Desc->getNumberOfCells();
8673 intersectEdge1.resize(nDescCell1);
8674 colinear2.resize(nDescCell2);
8675 subDiv2.resize(nDescCell2);
8676 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8678 std::vector<int> candidates1(1);
8679 int offset1=m1->getNumberOfNodes();
8680 int offset2=offset1+m2->getNumberOfNodes();
8681 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
8683 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8684 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8685 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8687 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8688 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8689 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8691 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8692 // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
8693 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8694 std::set<INTERP_KERNEL::Node *> nodes;
8695 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8696 std::size_t szz(nodes.size());
8697 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8698 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8699 for(std::size_t iii=0;iii<szz;iii++,itt++)
8700 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8701 // end of protection
8702 // Performs egde cutting:
8703 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8708 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8710 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8711 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8715 * This method performs the 2nd step of Partition of 2D mesh.
8716 * This method has 4 inputs :
8717 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8718 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8719 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
8720 * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
8721 * Nodes end up lying consecutively on a cutted edge.
8722 * \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.
8723 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
8724 * \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.
8725 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
8726 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
8728 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8729 const std::vector<double>& addCoo,
8730 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
8732 int offset1=m1->getNumberOfNodes();
8733 int ncell=m2->getNumberOfCells();
8734 const int *c=m2->getNodalConnectivity()->getConstPointer();
8735 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8736 const double *coo=m2->getCoords()->getConstPointer();
8737 const double *cooBis=m1->getCoords()->getConstPointer();
8738 int offset2=offset1+m2->getNumberOfNodes();
8739 intersectEdge.resize(ncell);
8740 for(int i=0;i<ncell;i++,cI++)
8742 const std::vector<int>& divs=subDiv[i];
8743 int nnode=cI[1]-cI[0]-1;
8744 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8745 std::map<INTERP_KERNEL::Node *, int> mapp22;
8746 for(int j=0;j<nnode;j++)
8748 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8749 int nnid=c[(*cI)+j+1];
8750 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8751 mapp22[nn]=nnid+offset1;
8753 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8754 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8755 ((*it).second.first)->decrRef();
8756 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8757 std::map<INTERP_KERNEL::Node *,int> mapp3;
8758 for(std::size_t j=0;j<divs.size();j++)
8761 INTERP_KERNEL::Node *tmp=0;
8763 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8765 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8767 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8771 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8772 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8779 * 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).
8780 * 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
8781 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8782 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8783 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8784 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8785 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8786 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8787 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8788 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8789 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8790 * \param [out] cut3DSuf input/output param.
8792 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8793 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8794 const int *desc, const int *descIndx,
8795 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8797 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8798 int nbOf3DSurfCell=(int)cut3DSurf.size();
8799 for(int i=0;i<nbOf3DSurfCell;i++)
8801 std::vector<int> res;
8802 int offset=descIndx[i];
8803 int nbOfSeg=descIndx[i+1]-offset;
8804 for(int j=0;j<nbOfSeg;j++)
8806 int edgeId=desc[offset+j];
8807 int status=cut3DCurve[edgeId];
8811 res.push_back(status);
8814 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8815 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8823 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8829 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8830 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8833 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8837 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8842 {// case when plane is on a multi colinear edge of a polyhedron
8843 if((int)res.size()==2*nbOfSeg)
8845 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8855 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8856 * 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).
8857 * 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
8858 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8859 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8860 * \param desc is the descending connectivity 3D->3DSurf
8861 * \param descIndx is the descending connectivity index 3D->3DSurf
8863 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8864 const int *desc, const int *descIndx,
8865 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8867 checkFullyDefined();
8868 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8870 const int *nodal3D=_nodal_connec->getConstPointer();
8871 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8872 int nbOfCells=getNumberOfCells();
8873 for(int i=0;i<nbOfCells;i++)
8875 std::map<int, std::set<int> > m;
8876 int offset=descIndx[i];
8877 int nbOfFaces=descIndx[i+1]-offset;
8880 for(int j=0;j<nbOfFaces;j++)
8882 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8883 if(p.first!=-1 && p.second!=-1)
8887 start=p.first; end=p.second;
8888 m[p.first].insert(p.second);
8889 m[p.second].insert(p.first);
8893 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8894 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8895 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8896 INTERP_KERNEL::NormalizedCellType cmsId;
8897 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8898 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8899 for(unsigned k=0;k<nbOfNodesSon;k++)
8901 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8902 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8909 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8913 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8914 const std::set<int>& s=(*it).second;
8915 std::set<int> s2; s2.insert(prev);
8917 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8920 int val=*s3.begin();
8921 conn.push_back(start);
8928 conn.push_back(end);
8931 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8932 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8933 cellIds->pushBackSilent(i);
8939 * 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
8940 * 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
8941 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8942 * 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
8943 * 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.
8945 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8947 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
8949 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8952 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8953 if(cm.getDimension()==2)
8955 const int *node=nodalConnBg+1;
8956 int startNode=*node++;
8957 double refX=coords[2*startNode];
8958 for(;node!=nodalConnEnd;node++)
8960 if(coords[2*(*node)]<refX)
8963 refX=coords[2*startNode];
8966 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8970 double angle0=-M_PI/2;
8975 double angleNext=0.;
8976 while(nextNode!=startNode)
8980 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8982 if(*node!=tmpOut.back() && *node!=prevNode)
8984 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8985 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8990 res=angle0-angleM+2.*M_PI;
8999 if(nextNode!=startNode)
9001 angle0=angleNext-M_PI;
9004 prevNode=tmpOut.back();
9005 tmpOut.push_back(nextNode);
9008 std::vector<int> tmp3(2*(sz-1));
9009 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9010 std::copy(nodalConnBg+1,nodalConnEnd,it);
9011 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9013 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9016 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9018 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9023 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9024 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9029 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9032 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9036 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9037 * 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.
9039 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9040 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9041 * \param [in,out] arr array in which the remove operation will be done.
9042 * \param [in,out] arrIndx array in the remove operation will modify
9043 * \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])
9044 * \return true if \b arr and \b arrIndx have been modified, false if not.
9046 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9048 if(!arrIndx || !arr)
9049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9050 if(offsetForRemoval<0)
9051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9052 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9053 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9054 int *arrIPtr=arrIndx->getPointer();
9057 const int *arrPtr=arr->getConstPointer();
9058 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9059 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9061 if(*arrIPtr-previousArrI>offsetForRemoval)
9063 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9065 if(s.find(*work)==s.end())
9066 arrOut.push_back(*work);
9069 previousArrI=*arrIPtr;
9070 *arrIPtr=(int)arrOut.size();
9072 if(arr->getNumberOfTuples()==(int)arrOut.size())
9074 arr->alloc((int)arrOut.size(),1);
9075 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9080 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9081 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9082 * The selection of extraction is done standardly in new2old format.
9083 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9085 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9086 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9087 * \param [in] arrIn arr origin array from which the extraction will be done.
9088 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9089 * \param [out] arrOut the resulting array
9090 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9091 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9093 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9094 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9096 if(!arrIn || !arrIndxIn)
9097 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9098 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9099 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9100 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9101 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9102 const int *arrInPtr=arrIn->getConstPointer();
9103 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9104 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9106 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9107 int maxSizeOfArr=arrIn->getNumberOfTuples();
9108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9109 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9110 arrIo->alloc((int)(sz+1),1);
9111 const int *idsIt=idsOfSelectBg;
9112 int *work=arrIo->getPointer();
9115 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9117 if(*idsIt>=0 && *idsIt<nbOfGrps)
9118 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9121 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9122 throw INTERP_KERNEL::Exception(oss.str().c_str());
9128 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9129 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9130 throw INTERP_KERNEL::Exception(oss.str().c_str());
9133 arro->alloc(lgth,1);
9134 work=arro->getPointer();
9135 idsIt=idsOfSelectBg;
9136 for(std::size_t i=0;i<sz;i++,idsIt++)
9138 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9139 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9142 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9143 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9144 throw INTERP_KERNEL::Exception(oss.str().c_str());
9148 arrIndexOut=arrIo.retn();
9152 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9153 * 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 ).
9154 * The selection of extraction is done standardly in new2old format.
9155 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9157 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9158 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9159 * \param [in] arrIn arr origin array from which the extraction will be done.
9160 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9161 * \param [out] arrOut the resulting array
9162 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9163 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9165 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9166 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9168 if(!arrIn || !arrIndxIn)
9169 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9170 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9171 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9173 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9174 const int *arrInPtr=arrIn->getConstPointer();
9175 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9176 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9178 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9179 int maxSizeOfArr=arrIn->getNumberOfTuples();
9180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9182 arrIo->alloc((int)(sz+1),1);
9183 int idsIt=idsOfSelectStart;
9184 int *work=arrIo->getPointer();
9187 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9189 if(idsIt>=0 && idsIt<nbOfGrps)
9190 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9193 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9194 throw INTERP_KERNEL::Exception(oss.str().c_str());
9200 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9201 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9202 throw INTERP_KERNEL::Exception(oss.str().c_str());
9205 arro->alloc(lgth,1);
9206 work=arro->getPointer();
9207 idsIt=idsOfSelectStart;
9208 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9210 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9211 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9214 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9215 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9216 throw INTERP_KERNEL::Exception(oss.str().c_str());
9220 arrIndexOut=arrIo.retn();
9224 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9225 * 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
9226 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9227 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9229 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9230 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9231 * \param [in] arrIn arr origin array from which the extraction will be done.
9232 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9233 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9234 * \param [in] srcArrIndex index array of \b srcArr
9235 * \param [out] arrOut the resulting array
9236 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9238 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9240 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9241 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9242 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9244 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9245 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9248 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9249 std::vector<bool> v(nbOfTuples,true);
9251 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9252 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9253 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9255 if(*it>=0 && *it<nbOfTuples)
9258 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9262 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9263 throw INTERP_KERNEL::Exception(oss.str().c_str());
9266 srcArrIndexPtr=srcArrIndex->getConstPointer();
9267 arrIo->alloc(nbOfTuples+1,1);
9268 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9269 const int *arrInPtr=arrIn->getConstPointer();
9270 const int *srcArrPtr=srcArr->getConstPointer();
9271 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9272 int *arroPtr=arro->getPointer();
9273 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9277 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9278 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9282 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9283 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9284 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9288 arrIndexOut=arrIo.retn();
9292 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9293 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9295 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9296 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9297 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9298 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9299 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9300 * \param [in] srcArrIndex index array of \b srcArr
9302 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9304 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9305 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9307 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9308 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9309 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9310 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9311 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9312 int *arrInOutPtr=arrInOut->getPointer();
9313 const int *srcArrPtr=srcArr->getConstPointer();
9314 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9316 if(*it>=0 && *it<nbOfTuples)
9318 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9319 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9322 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] !";
9323 throw INTERP_KERNEL::Exception(oss.str().c_str());
9328 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9329 throw INTERP_KERNEL::Exception(oss.str().c_str());
9335 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9336 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9337 * 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]].
9338 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9339 * A negative value in \b arrIn means that it is ignored.
9340 * 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.
9342 * \param [in] arrIn arr origin array from which the extraction will be done.
9343 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9344 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9345 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9347 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9349 int seed=0,nbOfDepthPeelingPerformed=0;
9350 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9354 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9355 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9356 * 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]].
9357 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9358 * A negative value in \b arrIn means that it is ignored.
9359 * 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.
9360 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9361 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9362 * \param [in] arrIn arr origin array from which the extraction will be done.
9363 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9364 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9365 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9366 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9367 * \sa MEDCouplingUMesh::partitionBySpreadZone
9369 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9371 nbOfDepthPeelingPerformed=0;
9373 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9374 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9377 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9381 std::vector<bool> fetched(nbOfTuples,false);
9382 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9385 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9387 nbOfDepthPeelingPerformed=0;
9388 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9389 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9390 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9391 std::vector<bool> fetched2(nbOfTuples,false);
9393 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9395 if(*seedElt>=0 && *seedElt<nbOfTuples)
9396 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9398 { 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()); }
9400 const int *arrInPtr=arrIn->getConstPointer();
9401 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9402 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9403 std::vector<int> idsToFetch1(seedBg,seedEnd);
9404 std::vector<int> idsToFetch2;
9405 std::vector<int> *idsToFetch=&idsToFetch1;
9406 std::vector<int> *idsToFetchOther=&idsToFetch2;
9407 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9409 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9410 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9412 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9413 std::swap(idsToFetch,idsToFetchOther);
9414 idsToFetchOther->clear();
9415 nbOfDepthPeelingPerformed++;
9417 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9420 int *retPtr=ret->getPointer();
9421 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9428 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9429 * 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
9430 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9431 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9433 * \param [in] start begin of set of ids of the input extraction (included)
9434 * \param [in] end end of set of ids of the input extraction (excluded)
9435 * \param [in] step step of the set of ids in range mode.
9436 * \param [in] arrIn arr origin array from which the extraction will be done.
9437 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9438 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9439 * \param [in] srcArrIndex index array of \b srcArr
9440 * \param [out] arrOut the resulting array
9441 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9443 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9445 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9446 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9447 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9449 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9453 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9455 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9456 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9457 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9459 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9461 if(it>=0 && it<nbOfTuples)
9462 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9465 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9466 throw INTERP_KERNEL::Exception(oss.str().c_str());
9469 srcArrIndexPtr=srcArrIndex->getConstPointer();
9470 arrIo->alloc(nbOfTuples+1,1);
9471 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9472 const int *arrInPtr=arrIn->getConstPointer();
9473 const int *srcArrPtr=srcArr->getConstPointer();
9474 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9475 int *arroPtr=arro->getPointer();
9476 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9478 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9481 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9482 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9486 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9487 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9491 arrIndexOut=arrIo.retn();
9495 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9496 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9498 * \param [in] start begin of set of ids of the input extraction (included)
9499 * \param [in] end end of set of ids of the input extraction (excluded)
9500 * \param [in] step step of the set of ids in range mode.
9501 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9502 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9503 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9504 * \param [in] srcArrIndex index array of \b srcArr
9506 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9508 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9509 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9511 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9512 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9513 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9514 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9515 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9516 int *arrInOutPtr=arrInOut->getPointer();
9517 const int *srcArrPtr=srcArr->getConstPointer();
9518 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9520 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9522 if(it>=0 && it<nbOfTuples)
9524 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9525 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9528 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9529 throw INTERP_KERNEL::Exception(oss.str().c_str());
9534 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9535 throw INTERP_KERNEL::Exception(oss.str().c_str());
9541 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9542 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9543 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9544 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9545 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9547 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9549 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9551 checkFullyDefined();
9552 int mdim=getMeshDimension();
9553 int spaceDim=getSpaceDimension();
9555 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9556 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9557 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9558 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9559 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9560 ret->setCoords(getCoords());
9561 ret->allocateCells((int)partition.size());
9563 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9565 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9570 cell=tmp->buildUnionOf2DMesh();
9573 cell=tmp->buildUnionOf3DMesh();
9576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9579 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9582 ret->finishInsertingCells();
9587 * This method partitions \b this into contiguous zone.
9588 * This method only needs a well defined connectivity. Coordinates are not considered here.
9589 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9591 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9593 int nbOfCellsCur=getNumberOfCells();
9594 std::vector<DataArrayInt *> ret;
9597 DataArrayInt *neigh=0,*neighI=0;
9598 computeNeighborsOfCells(neigh,neighI);
9599 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9600 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9601 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9603 while(seed<nbOfCellsCur)
9605 int nbOfPeelPerformed=0;
9606 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9607 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9609 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9610 ret.push_back((*it).retn());
9615 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9616 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9618 * \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.
9619 * \return a newly allocated DataArrayInt to be managed by the caller.
9620 * \throw In case of \a code has not the right format (typically of size 3*n)
9622 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9625 std::size_t nb=code.size()/3;
9626 if(code.size()%3!=0)
9627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9628 ret->alloc((int)nb,2);
9629 int *retPtr=ret->getPointer();
9630 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9632 retPtr[0]=code[3*i+2];
9633 retPtr[1]=code[3*i+2]+code[3*i+1];
9639 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9640 * All cells in \a this are expected to be linear 3D cells.
9641 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9642 * It leads to an increase to number of cells.
9643 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9644 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9645 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9647 * \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.
9648 * For all other cells, the splitting policy will be ignored.
9649 * \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.
9650 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9651 * an id of old cell producing it. The caller is to delete this array using
9652 * decrRef() as it is no more needed.
9653 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9655 * \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
9656 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9658 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9659 * \throw If \a this is not fully constituted with linear 3D cells.
9660 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9662 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9664 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9665 checkConnectivityFullyDefined();
9666 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9667 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9668 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9669 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
9670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9671 int *retPt(ret->getPointer());
9672 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9673 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9674 const int *oldc(_nodal_connec->begin());
9675 const int *oldci(_nodal_connec_index->begin());
9676 const double *coords(_coords->begin());
9677 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9679 std::vector<int> a; std::vector<double> b;
9680 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9681 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9682 const int *aa(&a[0]);
9685 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9687 *it=(-(*(it))-1+nbNodes);
9688 addPts->insertAtTheEnd(b.begin(),b.end());
9689 nbNodes+=(int)b.size()/3;
9691 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9692 newConn->insertAtTheEnd(aa,aa+4);
9694 if(!addPts->empty())
9696 addPts->rearrange(3);
9697 nbOfAdditionalPoints=addPts->getNumberOfTuples();
9698 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9699 ret0->setCoords(addPts);
9703 nbOfAdditionalPoints=0;
9704 ret0->setCoords(getCoords());
9706 ret0->setNodalConnectivity(newConn);
9708 ret->computeOffsets2();
9709 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9713 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9714 _own_cell(true),_cell_id(-1),_nb_cell(0)
9719 _nb_cell=mesh->getNumberOfCells();
9723 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9731 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9732 _own_cell(false),_cell_id(bg-1),
9739 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9742 if(_cell_id<_nb_cell)
9751 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9757 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9759 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9762 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9768 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9776 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9782 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9787 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9792 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9794 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9797 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9802 _nb_cell=mesh->getNumberOfCells();
9806 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9813 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9815 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9816 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9817 if(_cell_id<_nb_cell)
9819 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9820 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9821 int startId=_cell_id;
9822 _cell_id+=nbOfElems;
9823 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9829 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9833 _conn=mesh->getNodalConnectivity()->getPointer();
9834 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9838 void MEDCouplingUMeshCell::next()
9840 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9845 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9848 std::string MEDCouplingUMeshCell::repr() const
9850 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9852 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9854 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9858 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9861 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9863 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9864 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9866 return INTERP_KERNEL::NORM_ERROR;
9869 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9872 if(_conn_lgth!=NOTICABLE_FIRST_VAL)