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 * \if ENABLE_EXAMPLES
318 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
319 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
322 void MEDCouplingUMesh::allocateCells(int nbOfCells)
325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
326 if(_nodal_connec_index)
328 _nodal_connec_index->decrRef();
332 _nodal_connec->decrRef();
334 _nodal_connec_index=DataArrayInt::New();
335 _nodal_connec_index->reserve(nbOfCells+1);
336 _nodal_connec_index->pushBackSilent(0);
337 _nodal_connec=DataArrayInt::New();
338 _nodal_connec->reserve(2*nbOfCells);
344 * Appends a cell to the connectivity array. For deeper understanding what is
345 * happening see \ref MEDCouplingUMeshNodalConnectivity.
346 * \param [in] type - type of cell to add.
347 * \param [in] size - number of nodes constituting this cell.
348 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
350 * \if ENABLE_EXAMPLES
351 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
352 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
355 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
357 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
358 if(_nodal_connec_index==0)
359 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
360 if((int)cm.getDimension()==_mesh_dim)
363 if(size!=(int)cm.getNumberOfNodes())
365 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
366 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
367 throw INTERP_KERNEL::Exception(oss.str().c_str());
369 int idx=_nodal_connec_index->back();
371 _nodal_connec_index->pushBackSilent(val);
372 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
377 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
378 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
379 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
380 throw INTERP_KERNEL::Exception(oss.str().c_str());
385 * Compacts data arrays to release unused memory. This method is to be called after
386 * finishing cell insertion using \a this->insertNextCell().
388 * \if ENABLE_EXAMPLES
389 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
390 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
393 void MEDCouplingUMesh::finishInsertingCells()
395 _nodal_connec->pack();
396 _nodal_connec_index->pack();
397 _nodal_connec->declareAsNew();
398 _nodal_connec_index->declareAsNew();
403 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
404 * Useful for python users.
406 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
408 return new MEDCouplingUMeshCellIterator(this);
412 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
413 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
414 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
415 * Useful for python users.
417 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
419 if(!checkConsecutiveCellTypes())
420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
421 return new MEDCouplingUMeshCellByTypeEntry(this);
425 * Returns a set of all cell types available in \a this mesh.
426 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
427 * \warning this method does not throw any exception even if \a this is not defined.
428 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
430 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
436 * This method returns the sorted list of geometric types in \a this.
437 * 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
438 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
440 * \throw if connectivity in \a this is not correctly defined.
442 * \sa MEDCouplingMesh::getAllGeoTypes
444 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
446 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
447 checkConnectivityFullyDefined();
448 int nbOfCells(getNumberOfCells());
451 if(getMeshLength()<1)
452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
453 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
454 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
455 for(int i=1;i<nbOfCells;i++,ci++)
456 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
457 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
462 * This method is a method that compares \a this and \a other.
463 * This method compares \b all attributes, even names and component names.
465 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
469 std::ostringstream oss; oss.precision(15);
470 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
473 reason="mesh given in input is not castable in MEDCouplingUMesh !";
476 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
478 if(_mesh_dim!=otherC->_mesh_dim)
480 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
484 if(_types!=otherC->_types)
486 oss << "umesh geometric type mismatch :\nThis geometric types are :";
487 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
488 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489 oss << "\nOther geometric types are :";
490 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
491 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
495 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
496 if(_nodal_connec==0 || otherC->_nodal_connec==0)
498 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
501 if(_nodal_connec!=otherC->_nodal_connec)
502 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
504 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
507 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
510 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
513 if(_nodal_connec_index!=otherC->_nodal_connec_index)
514 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
516 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
523 * Checks if data arrays of this mesh (node coordinates, nodal
524 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
526 * \param [in] other - the mesh to compare with.
527 * \param [in] prec - precision value used to compare node coordinates.
528 * \return bool - \a true if the two meshes are same.
530 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
532 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
535 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
537 if(_mesh_dim!=otherC->_mesh_dim)
539 if(_types!=otherC->_types)
541 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
542 if(_nodal_connec==0 || otherC->_nodal_connec==0)
544 if(_nodal_connec!=otherC->_nodal_connec)
545 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
547 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
548 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
550 if(_nodal_connec_index!=otherC->_nodal_connec_index)
551 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
557 * Checks if \a this and \a other meshes are geometrically equivalent with high
558 * probability, else an exception is thrown. The meshes are considered equivalent if
559 * (1) meshes contain the same number of nodes and the same number of elements of the
560 * same types (2) three cells of the two meshes (first, last and middle) are based
561 * on coincident nodes (with a specified precision).
562 * \param [in] other - the mesh to compare with.
563 * \param [in] prec - the precision used to compare nodes of the two meshes.
564 * \throw If the two meshes do not match.
566 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
568 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
569 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
571 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
575 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
576 * cells each node belongs to.
577 * \warning For speed reasons, this method does not check if node ids in the nodal
578 * connectivity correspond to the size of node coordinates array.
579 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
580 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
581 * dividing cell ids in \a revNodal into groups each referring to one
582 * node. Its every element (except the last one) is an index pointing to the
583 * first id of a group of cells. For example cells sharing the node #1 are
584 * described by following range of indices:
585 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
586 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
587 * Number of cells sharing the *i*-th node is
588 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
589 * \throw If the coordinates array is not set.
590 * \throw If the nodal connectivity of cells is not defined.
592 * \if ENABLE_EXAMPLES
593 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
594 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
597 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
600 int nbOfNodes=getNumberOfNodes();
601 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
602 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
603 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
604 const int *conn=_nodal_connec->getConstPointer();
605 const int *connIndex=_nodal_connec_index->getConstPointer();
606 int nbOfCells=getNumberOfCells();
607 int nbOfEltsInRevNodal=0;
608 for(int eltId=0;eltId<nbOfCells;eltId++)
610 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
611 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
612 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
613 if(*iter>=0)//for polyhedrons
615 nbOfEltsInRevNodal++;
616 revNodalIndxPtr[(*iter)+1]++;
619 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
620 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
621 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
622 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
623 for(int eltId=0;eltId<nbOfCells;eltId++)
625 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
626 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
627 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
628 if(*iter>=0)//for polyhedrons
629 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
635 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
640 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
646 if(cm.getOrientationStatus(nb,conn1,conn2))
653 class MinusOneSonsGenerator
656 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
657 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
658 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
659 static const int DELTA=1;
661 const INTERP_KERNEL::CellModel& _cm;
664 class MinusOneSonsGeneratorBiQuadratic
667 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670 static const int DELTA=1;
672 const INTERP_KERNEL::CellModel& _cm;
675 class MinusTwoSonsGenerator
678 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
680 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681 static const int DELTA=2;
683 const INTERP_KERNEL::CellModel& _cm;
689 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
690 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
691 * describing correspondence between cells of \a this and the result meshes are
692 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
693 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
694 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
695 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
696 * \warning For speed reasons, this method does not check if node ids in the nodal
697 * connectivity correspond to the size of node coordinates array.
698 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
699 * to write this mesh to the MED file, its cells must be sorted using
700 * sortCellsInMEDFileFrmt().
701 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
702 * each cell of \a this mesh.
703 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
704 * dividing cell ids in \a desc into groups each referring to one
705 * cell of \a this mesh. Its every element (except the last one) is an index
706 * pointing to the first id of a group of cells. For example cells of the
707 * result mesh bounding the cell #1 of \a this mesh are described by following
709 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
710 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
711 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
712 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
713 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
714 * by each cell of the result mesh.
715 * \param [in,out] revDescIndx - the array, of length one more than number of cells
716 * in the result mesh,
717 * dividing cell ids in \a revDesc into groups each referring to one
718 * cell of the result mesh the same way as \a descIndx divides \a desc.
719 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
720 * delete this mesh using decrRef() as it is no more needed.
721 * \throw If the coordinates array is not set.
722 * \throw If the nodal connectivity of cells is node defined.
723 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
724 * revDescIndx == NULL.
726 * \if ENABLE_EXAMPLES
727 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
728 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
730 * \sa buildDescendingConnectivity2()
732 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
734 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
738 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
739 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
740 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
741 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
742 * \sa MEDCouplingUMesh::buildDescendingConnectivity
744 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
747 if(getMeshDimension()!=3)
748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
749 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
753 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
754 * this->getMeshDimension(), that bound cells of \a this mesh. In
755 * addition arrays describing correspondence between cells of \a this and the result
756 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
757 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
758 * mesh. This method differs from buildDescendingConnectivity() in that apart
759 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
760 * result meshes. So a positive id means that order of nodes in corresponding cells
761 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
762 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
763 * i.e. cell ids are one-based.
764 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
765 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
766 * \warning For speed reasons, this method does not check if node ids in the nodal
767 * connectivity correspond to the size of node coordinates array.
768 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
769 * to write this mesh to the MED file, its cells must be sorted using
770 * sortCellsInMEDFileFrmt().
771 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
772 * each cell of \a this mesh.
773 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
774 * dividing cell ids in \a desc into groups each referring to one
775 * cell of \a this mesh. Its every element (except the last one) is an index
776 * pointing to the first id of a group of cells. For example cells of the
777 * result mesh bounding the cell #1 of \a this mesh are described by following
779 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
780 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
781 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
782 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
783 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
784 * by each cell of the result mesh.
785 * \param [in,out] revDescIndx - the array, of length one more than number of cells
786 * in the result mesh,
787 * dividing cell ids in \a revDesc into groups each referring to one
788 * cell of the result mesh the same way as \a descIndx divides \a desc.
789 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
790 * shares the node coordinates array with \a this mesh. The caller is to
791 * delete this mesh using decrRef() as it is no more needed.
792 * \throw If the coordinates array is not set.
793 * \throw If the nodal connectivity of cells is node defined.
794 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
795 * revDescIndx == NULL.
797 * \if ENABLE_EXAMPLES
798 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
799 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
801 * \sa buildDescendingConnectivity()
803 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
805 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
809 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
810 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
811 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
812 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
814 * \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
815 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
816 * \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.
818 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
824 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
826 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
830 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
831 * 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,
832 * excluding a set of meshdim-1 cells in input descending connectivity.
833 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
834 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
835 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
837 * \param [in] desc descending connectivity array.
838 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
839 * \param [in] revDesc reverse descending connectivity array.
840 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
841 * \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
842 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843 * \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.
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
848 if(!desc || !descIndx || !revDesc || !revDescIndx)
849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850 const int *descPtr=desc->getConstPointer();
851 const int *descIPtr=descIndx->getConstPointer();
852 const int *revDescPtr=revDesc->getConstPointer();
853 const int *revDescIPtr=revDescIndx->getConstPointer();
855 int nbCells=descIndx->getNumberOfTuples()-1;
856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858 int *out1Ptr=out1->getPointer();
860 out0->reserve(desc->getNumberOfTuples());
861 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
863 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
865 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
867 out0->insertAtTheEnd(s.begin(),s.end());
869 *out1Ptr=out0->getNumberOfTuples();
871 neighbors=out0.retn();
872 neighborsIndx=out1.retn();
878 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
879 * For speed reasons no check of this will be done.
881 template<class SonsGenerator>
882 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
884 if(!desc || !descIndx || !revDesc || !revDescIndx)
885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
886 checkConnectivityFullyDefined();
887 int nbOfCells=getNumberOfCells();
888 int nbOfNodes=getNumberOfNodes();
889 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
890 int *revNodalIndxPtr=revNodalIndx->getPointer();
891 const int *conn=_nodal_connec->getConstPointer();
892 const int *connIndex=_nodal_connec_index->getConstPointer();
893 std::string name="Mesh constituent of "; name+=getName();
894 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
895 ret->setCoords(getCoords());
896 ret->allocateCells(2*nbOfCells);
897 descIndx->alloc(nbOfCells+1,1);
898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
899 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
900 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
902 int pos=connIndex[eltId];
903 int posP1=connIndex[eltId+1];
904 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
905 SonsGenerator sg(cm);
906 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
907 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
908 for(unsigned i=0;i<nbOfSons;i++)
910 INTERP_KERNEL::NormalizedCellType cmsId;
911 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
912 for(unsigned k=0;k<nbOfNodesSon;k++)
914 revNodalIndxPtr[tmp[k]+1]++;
915 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
916 revDesc2->pushBackSilent(eltId);
918 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
920 int nbOfCellsM1=ret->getNumberOfCells();
921 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
923 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
924 int *revNodalPtr=revNodal->getPointer();
925 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
926 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
927 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
929 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
930 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
931 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
932 if(*iter>=0)//for polyhedrons
933 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
936 DataArrayInt *commonCells=0,*commonCellsI=0;
937 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
939 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
940 int newNbOfCellsM1=-1;
941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
942 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
943 std::vector<bool> isImpacted(nbOfCellsM1,false);
944 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
945 for(int work2=work[0];work2!=work[1];work2++)
946 isImpacted[commonCellsPtr[work2]]=true;
947 const int *o2nM1Ptr=o2nM1->getConstPointer();
948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
949 const int *n2oM1Ptr=n2oM1->getConstPointer();
950 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
951 ret2->copyTinyInfoFrom(this);
952 desc->alloc(descIndx->back(),1);
953 int *descPtr=desc->getPointer();
954 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
955 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
958 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
961 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
963 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
964 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
967 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
970 revDesc->reserve(newNbOfCellsM1);
971 revDescIndx->alloc(newNbOfCellsM1+1,1);
972 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
973 const int *revDesc2Ptr=revDesc2->getConstPointer();
974 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
976 int oldCellIdM1=n2oM1Ptr[i];
977 if(!isImpacted[oldCellIdM1])
979 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
980 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
984 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
985 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
986 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
994 struct MEDCouplingAccVisit
996 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
997 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
998 int _new_nb_of_nodes;
1004 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1005 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1006 * array of cell ids. Pay attention that after conversion all algorithms work slower
1007 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1008 * conversion due presence of invalid ids in the array of cells to convert, as a
1009 * result \a this mesh contains some already converted elements. In this case the 2D
1010 * mesh remains valid but 3D mesh becomes \b inconsistent!
1011 * \warning This method can significantly modify the order of geometric types in \a this,
1012 * hence, to write this mesh to the MED file, its cells must be sorted using
1013 * sortCellsInMEDFileFrmt().
1014 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1015 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1016 * cellIdsToConvertBg.
1017 * \throw If the coordinates array is not set.
1018 * \throw If the nodal connectivity of cells is node defined.
1019 * \throw If dimension of \a this mesh is not either 2 or 3.
1021 * \if ENABLE_EXAMPLES
1022 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1023 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1026 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1028 checkFullyDefined();
1029 int dim=getMeshDimension();
1031 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1032 int nbOfCells(getNumberOfCells());
1035 const int *connIndex=_nodal_connec_index->getConstPointer();
1036 int *conn=_nodal_connec->getPointer();
1037 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1039 if(*iter>=0 && *iter<nbOfCells)
1041 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1042 if(!cm.isQuadratic())
1043 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1045 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1049 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1050 oss << " in range [0," << nbOfCells << ") !";
1051 throw INTERP_KERNEL::Exception(oss.str().c_str());
1057 int *connIndex(_nodal_connec_index->getPointer());
1058 const int *connOld(_nodal_connec->getConstPointer());
1059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1060 std::vector<bool> toBeDone(nbOfCells,false);
1061 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1063 if(*iter>=0 && *iter<nbOfCells)
1064 toBeDone[*iter]=true;
1067 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1068 oss << " in range [0," << nbOfCells << ") !";
1069 throw INTERP_KERNEL::Exception(oss.str().c_str());
1072 for(int cellId=0;cellId<nbOfCells;cellId++)
1074 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1075 int lgthOld(posP1-pos-1);
1076 if(toBeDone[cellId])
1078 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1079 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1080 int *tmp(new int[nbOfFaces*lgthOld+1]);
1081 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1082 for(unsigned j=0;j<nbOfFaces;j++)
1084 INTERP_KERNEL::NormalizedCellType type;
1085 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1089 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1090 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1091 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1096 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1097 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1100 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1106 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1107 * polyhedrons (if \a this is a 3D mesh).
1108 * \warning As this method is purely for user-friendliness and no optimization is
1109 * done to avoid construction of a useless vector, this method can be costly
1111 * \throw If the coordinates array is not set.
1112 * \throw If the nodal connectivity of cells is node defined.
1113 * \throw If dimension of \a this mesh is not either 2 or 3.
1115 void MEDCouplingUMesh::convertAllToPoly()
1117 int nbOfCells=getNumberOfCells();
1118 std::vector<int> cellIds(nbOfCells);
1119 for(int i=0;i<nbOfCells;i++)
1121 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1125 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1126 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1127 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1128 * base facet of the volume and the second half of nodes describes an opposite facet
1129 * having the same number of nodes as the base one. This method converts such
1130 * connectivity to a valid polyhedral format where connectivity of each facet is
1131 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1132 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1133 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1134 * a correct orientation of the first facet of a polyhedron, else orientation of a
1135 * corrected cell is reverse.<br>
1136 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1137 * it releases the user from boring description of polyhedra connectivity in the valid
1139 * \throw If \a this->getMeshDimension() != 3.
1140 * \throw If \a this->getSpaceDimension() != 3.
1141 * \throw If the nodal connectivity of cells is not defined.
1142 * \throw If the coordinates array is not set.
1143 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1144 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1146 * \if ENABLE_EXAMPLES
1147 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1148 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1151 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1153 checkFullyDefined();
1154 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1155 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1156 int nbOfCells=getNumberOfCells();
1157 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1158 newCi->alloc(nbOfCells+1,1);
1159 int *newci=newCi->getPointer();
1160 const int *ci=_nodal_connec_index->getConstPointer();
1161 const int *c=_nodal_connec->getConstPointer();
1163 for(int i=0;i<nbOfCells;i++)
1165 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1166 if(type==INTERP_KERNEL::NORM_POLYHED)
1168 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1170 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1171 throw INTERP_KERNEL::Exception(oss.str().c_str());
1173 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1176 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 !";
1177 throw INTERP_KERNEL::Exception(oss.str().c_str());
1180 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)
1183 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1186 newC->alloc(newci[nbOfCells],1);
1187 int *newc=newC->getPointer();
1188 for(int i=0;i<nbOfCells;i++)
1190 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1191 if(type==INTERP_KERNEL::NORM_POLYHED)
1193 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1194 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1196 for(std::size_t j=0;j<n1;j++)
1198 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1200 newc[n1+5*j+1]=c[ci[i]+1+j];
1201 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1202 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1203 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1208 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1210 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1211 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1216 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1217 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1218 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1219 * to write this mesh to the MED file, its cells must be sorted using
1220 * sortCellsInMEDFileFrmt().
1221 * \return \c true if at least one cell has been converted, \c false else. In the
1222 * last case the nodal connectivity remains unchanged.
1223 * \throw If the coordinates array is not set.
1224 * \throw If the nodal connectivity of cells is not defined.
1225 * \throw If \a this->getMeshDimension() < 0.
1227 bool MEDCouplingUMesh::unPolyze()
1229 checkFullyDefined();
1230 int mdim=getMeshDimension();
1232 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1235 int nbOfCells=getNumberOfCells();
1238 int initMeshLgth=getMeshLength();
1239 int *conn=_nodal_connec->getPointer();
1240 int *index=_nodal_connec_index->getPointer();
1245 for(int i=0;i<nbOfCells;i++)
1247 lgthOfCurCell=index[i+1]-posOfCurCell;
1248 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1249 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1250 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1254 switch(cm.getDimension())
1258 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1259 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1260 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1265 int nbOfFaces,lgthOfPolyhConn;
1266 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1267 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1272 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1276 ret=ret || (newType!=type);
1277 conn[newPos]=newType;
1279 posOfCurCell=index[i+1];
1284 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1285 newPos+=lgthOfCurCell;
1286 posOfCurCell+=lgthOfCurCell;
1290 if(newPos!=initMeshLgth)
1291 _nodal_connec->reAlloc(newPos);
1298 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1299 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1300 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1302 * \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
1305 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1307 checkFullyDefined();
1308 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1310 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1311 coords->recenterForMaxPrecision(eps);
1313 int nbOfCells=getNumberOfCells();
1314 const int *conn=_nodal_connec->getConstPointer();
1315 const int *index=_nodal_connec_index->getConstPointer();
1316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1317 connINew->alloc(nbOfCells+1,1);
1318 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1321 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1323 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1325 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1329 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1330 *connINewPtr=connNew->getNumberOfTuples();
1333 setConnectivity(connNew,connINew,false);
1337 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1338 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1339 * the format of returned DataArrayInt instance.
1341 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1342 * \sa MEDCouplingUMesh::getNodeIdsInUse
1344 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1346 checkConnectivityFullyDefined();
1347 int nbOfCells=getNumberOfCells();
1348 const int *connIndex=_nodal_connec_index->getConstPointer();
1349 const int *conn=_nodal_connec->getConstPointer();
1350 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1351 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1352 std::vector<bool> retS(maxElt,false);
1353 for(int i=0;i<nbOfCells;i++)
1354 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1358 for(int i=0;i<maxElt;i++)
1361 DataArrayInt *ret=DataArrayInt::New();
1363 int *retPtr=ret->getPointer();
1364 for(int i=0;i<maxElt;i++)
1371 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1372 * \sa MEDCouplingUMesh::getNodeIdsInUse
1374 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1376 int nbOfNodes=(int)nodeIdsInUse.size();
1377 int nbOfCells=getNumberOfCells();
1378 const int *connIndex=_nodal_connec_index->getConstPointer();
1379 const int *conn=_nodal_connec->getConstPointer();
1380 for(int i=0;i<nbOfCells;i++)
1381 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1384 if(conn[j]<nbOfNodes)
1385 nodeIdsInUse[conn[j]]=true;
1388 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1389 throw INTERP_KERNEL::Exception(oss.str().c_str());
1395 * Finds nodes not used in any cell and returns an array giving a new id to every node
1396 * by excluding the unused nodes, for which the array holds -1. The result array is
1397 * a mapping in "Old to New" mode.
1398 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1399 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1400 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1401 * if the node is unused or a new id else. The caller is to delete this
1402 * array using decrRef() as it is no more needed.
1403 * \throw If the coordinates array is not set.
1404 * \throw If the nodal connectivity of cells is not defined.
1405 * \throw If the nodal connectivity includes an invalid id.
1407 * \if ENABLE_EXAMPLES
1408 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1409 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1411 * \sa computeNodeIdsAlg()
1413 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1416 int nbOfNodes=getNumberOfNodes();
1417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1418 ret->alloc(nbOfNodes,1);
1419 int *traducer=ret->getPointer();
1420 std::fill(traducer,traducer+nbOfNodes,-1);
1421 int nbOfCells=getNumberOfCells();
1422 const int *connIndex=_nodal_connec_index->getConstPointer();
1423 const int *conn=_nodal_connec->getConstPointer();
1424 for(int i=0;i<nbOfCells;i++)
1425 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1428 if(conn[j]<nbOfNodes)
1429 traducer[conn[j]]=1;
1432 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1433 throw INTERP_KERNEL::Exception(oss.str().c_str());
1436 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1437 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1442 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1443 * For each cell in \b this the number of nodes constituting cell is computed.
1444 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1445 * So for pohyhedrons some nodes can be counted several times in the returned result.
1447 * \return a newly allocated array
1448 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1450 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1452 checkConnectivityFullyDefined();
1453 int nbOfCells=getNumberOfCells();
1454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1455 ret->alloc(nbOfCells,1);
1456 int *retPtr=ret->getPointer();
1457 const int *conn=getNodalConnectivity()->getConstPointer();
1458 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1459 for(int i=0;i<nbOfCells;i++,retPtr++)
1461 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1462 *retPtr=connI[i+1]-connI[i]-1;
1464 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1470 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1471 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1473 * \return DataArrayInt * - new object to be deallocated by the caller.
1474 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1476 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1478 checkConnectivityFullyDefined();
1479 int nbOfCells=getNumberOfCells();
1480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1481 ret->alloc(nbOfCells,1);
1482 int *retPtr=ret->getPointer();
1483 const int *conn=getNodalConnectivity()->getConstPointer();
1484 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1485 for(int i=0;i<nbOfCells;i++,retPtr++)
1487 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1488 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1489 *retPtr=(int)s.size();
1493 *retPtr=(int)s.size();
1500 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1501 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1503 * \return a newly allocated array
1505 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1507 checkConnectivityFullyDefined();
1508 int nbOfCells=getNumberOfCells();
1509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1510 ret->alloc(nbOfCells,1);
1511 int *retPtr=ret->getPointer();
1512 const int *conn=getNodalConnectivity()->getConstPointer();
1513 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1514 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1516 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1517 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1523 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1524 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1525 * array mean that the corresponding old node is no more used.
1526 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1527 * this->getNumberOfNodes() before call of this method. The caller is to
1528 * delete this array using decrRef() as it is no more needed.
1529 * \throw If the coordinates array is not set.
1530 * \throw If the nodal connectivity of cells is not defined.
1531 * \throw If the nodal connectivity includes an invalid id.
1533 * \if ENABLE_EXAMPLES
1534 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1535 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1538 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1540 return MEDCouplingPointSet::zipCoordsTraducer();
1544 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1545 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1547 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1552 return AreCellsEqual0(conn,connI,cell1,cell2);
1554 return AreCellsEqual1(conn,connI,cell1,cell2);
1556 return AreCellsEqual2(conn,connI,cell1,cell2);
1558 return AreCellsEqual3(conn,connI,cell1,cell2);
1560 return AreCellsEqual7(conn,connI,cell1,cell2);
1562 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1566 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1568 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1570 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1571 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1576 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1578 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1580 int sz=connI[cell1+1]-connI[cell1];
1581 if(sz==connI[cell2+1]-connI[cell2])
1583 if(conn[connI[cell1]]==conn[connI[cell2]])
1585 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1586 unsigned dim=cm.getDimension();
1592 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1593 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1594 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1595 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1596 return work!=tmp+sz1?1:0;
1599 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1609 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1611 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1613 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1615 if(conn[connI[cell1]]==conn[connI[cell2]])
1617 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1618 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1626 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1628 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1630 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1633 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1640 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1642 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1644 int sz=connI[cell1+1]-connI[cell1];
1645 if(sz==connI[cell2+1]-connI[cell2])
1647 if(conn[connI[cell1]]==conn[connI[cell2]])
1649 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1650 unsigned dim=cm.getDimension();
1656 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1657 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1658 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1659 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1664 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1665 std::reverse_iterator<int *> it2((int *)tmp);
1666 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1672 return work!=tmp+sz1?1:0;
1675 {//case of SEG2 and SEG3
1676 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1678 if(!cm.isQuadratic())
1680 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1681 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1682 if(std::equal(it1,it2,conn+connI[cell2]+1))
1688 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])
1695 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1702 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1703 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1704 * and result remains unchanged.
1705 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1706 * If in 'candidates' pool -1 value is considered as an empty value.
1707 * WARNING this method returns only ONE set of result !
1709 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1711 if(candidates.size()<1)
1714 std::vector<int>::const_iterator iter=candidates.begin();
1715 int start=(*iter++);
1716 for(;iter!=candidates.end();iter++)
1718 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1723 result->pushBackSilent(start);
1727 result->pushBackSilent(*iter);
1729 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1736 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1737 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1739 * \param [in] compType input specifying the technique used to compare cells each other.
1740 * - 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.
1741 * - 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)
1742 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1743 * - 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
1744 * can be used for users not sensitive to orientation of cell
1745 * \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.
1746 * \param [out] commonCells
1747 * \param [out] commonCellsI
1748 * \return the correspondance array old to new in a newly allocated array.
1751 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1754 getReverseNodalConnectivity(revNodal,revNodalI);
1755 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1758 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1759 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1762 int nbOfCells=nodalI->getNumberOfTuples()-1;
1763 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1764 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1765 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1766 std::vector<bool> isFetched(nbOfCells,false);
1769 for(int i=0;i<nbOfCells;i++)
1773 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1774 std::vector<int> v,v2;
1775 if(connOfNode!=connPtr+connIPtr[i+1])
1777 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1778 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1781 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1785 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1786 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1787 v2.resize(std::distance(v2.begin(),it));
1791 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1793 int pos=commonCellsI->back();
1794 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1795 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1796 isFetched[*it]=true;
1804 for(int i=startCellId;i<nbOfCells;i++)
1808 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1809 std::vector<int> v,v2;
1810 if(connOfNode!=connPtr+connIPtr[i+1])
1812 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1815 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1819 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1820 v2.resize(std::distance(v2.begin(),it));
1824 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1826 int pos=commonCellsI->back();
1827 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1828 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1829 isFetched[*it]=true;
1835 commonCellsArr=commonCells.retn();
1836 commonCellsIArr=commonCellsI.retn();
1840 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1841 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1842 * than \a other->getNumberOfCells() in the returned array means that there is no
1843 * corresponding cell in \a this mesh.
1844 * It is expected that \a this and \a other meshes share the same node coordinates
1845 * array, if it is not so an exception is thrown.
1846 * \param [in] other - the mesh to compare with.
1847 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1848 * valid values [0,1,2], see zipConnectivityTraducer().
1849 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1850 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1851 * values. The caller is to delete this array using
1852 * decrRef() as it is no more needed.
1853 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1856 * \if ENABLE_EXAMPLES
1857 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1858 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1860 * \sa checkDeepEquivalOnSameNodesWith()
1861 * \sa checkGeoEquivalWith()
1863 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1865 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1866 int nbOfCells=getNumberOfCells();
1867 static const int possibleCompType[]={0,1,2};
1868 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1870 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1871 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1873 throw INTERP_KERNEL::Exception(oss.str().c_str());
1875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1876 arr=o2n->substr(nbOfCells);
1877 arr->setName(other->getName());
1879 if(other->getNumberOfCells()==0)
1881 return arr->getMaxValue(tmp)<nbOfCells;
1885 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1886 * This method tries to determine if \b other is fully included in \b this.
1887 * The main difference is that this method is not expected to throw exception.
1888 * This method has two outputs :
1890 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1891 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1893 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1895 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1896 DataArrayInt *commonCells=0,*commonCellsI=0;
1897 int thisNbCells=getNumberOfCells();
1898 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1900 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1901 int otherNbCells=other->getNumberOfCells();
1902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1903 arr2->alloc(otherNbCells,1);
1904 arr2->fillWithZero();
1905 int *arr2Ptr=arr2->getPointer();
1906 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1907 for(int i=0;i<nbOfCommon;i++)
1909 int start=commonCellsPtr[commonCellsIPtr[i]];
1910 if(start<thisNbCells)
1912 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1914 int sig=commonCellsPtr[j]>0?1:-1;
1915 int val=std::abs(commonCellsPtr[j])-1;
1916 if(val>=thisNbCells)
1917 arr2Ptr[val-thisNbCells]=sig*(start+1);
1921 arr2->setName(other->getName());
1922 if(arr2->presenceOfValue(0))
1928 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1932 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1934 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1935 std::vector<const MEDCouplingUMesh *> ms(2);
1938 return MergeUMeshesOnSameCoords(ms);
1942 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1943 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1944 * cellIds is not given explicitely but by a range python like.
1946 * \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.
1947 * \return a newly allocated
1949 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1950 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1952 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1954 if(getMeshDimension()!=-1)
1955 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1958 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1960 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1962 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1964 return const_cast<MEDCouplingUMesh *>(this);
1969 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1970 * The result mesh shares or not the node coordinates array with \a this mesh depending
1971 * on \a keepCoords parameter.
1972 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1973 * to write this mesh to the MED file, its cells must be sorted using
1974 * sortCellsInMEDFileFrmt().
1975 * \param [in] begin - an array of cell ids to include to the new mesh.
1976 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1977 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1978 * array of \a this mesh, else "free" nodes are removed from the result mesh
1979 * by calling zipCoords().
1980 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1981 * to delete this mesh using decrRef() as it is no more needed.
1982 * \throw If the coordinates array is not set.
1983 * \throw If the nodal connectivity of cells is not defined.
1984 * \throw If any cell id in the array \a begin is not valid.
1986 * \if ENABLE_EXAMPLES
1987 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1988 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1991 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1993 if(getMeshDimension()!=-1)
1994 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1998 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2000 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2002 return const_cast<MEDCouplingUMesh *>(this);
2007 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2009 * 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.
2010 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2011 * The number of cells of \b this will remain the same with this method.
2013 * \param [in] begin begin of cell ids (included) of cells in this to assign
2014 * \param [in] end end of cell ids (excluded) of cells in this to assign
2015 * \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 ).
2016 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2018 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2020 checkConnectivityFullyDefined();
2021 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2022 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2023 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2024 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2026 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2027 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2028 throw INTERP_KERNEL::Exception(oss.str().c_str());
2030 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2031 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2033 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2034 throw INTERP_KERNEL::Exception(oss.str().c_str());
2036 int nbOfCells=getNumberOfCells();
2037 bool easyAssign=true;
2038 const int *connI=_nodal_connec_index->getConstPointer();
2039 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2040 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2042 if(*it>=0 && *it<nbOfCells)
2044 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2048 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2049 throw INTERP_KERNEL::Exception(oss.str().c_str());
2054 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2059 DataArrayInt *arrOut=0,*arrIOut=0;
2060 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2062 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2063 setConnectivity(arrOut,arrIOut,true);
2067 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2069 checkConnectivityFullyDefined();
2070 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2071 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2072 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2073 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2075 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2076 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2077 throw INTERP_KERNEL::Exception(oss.str().c_str());
2079 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2080 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2082 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2083 throw INTERP_KERNEL::Exception(oss.str().c_str());
2085 int nbOfCells=getNumberOfCells();
2086 bool easyAssign=true;
2087 const int *connI=_nodal_connec_index->getConstPointer();
2088 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2090 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2092 if(it>=0 && it<nbOfCells)
2094 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2098 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2099 throw INTERP_KERNEL::Exception(oss.str().c_str());
2104 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2109 DataArrayInt *arrOut=0,*arrIOut=0;
2110 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113 setConnectivity(arrOut,arrIOut,true);
2118 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2119 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2120 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2121 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2123 * \param [in] begin input start of array of node ids.
2124 * \param [in] end input end of array of node ids.
2125 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2126 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2128 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2131 checkConnectivityFullyDefined();
2133 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2134 std::vector<bool> fastFinder(sz,false);
2135 for(const int *work=begin;work!=end;work++)
2136 if(*work>=0 && *work<sz)
2137 fastFinder[*work]=true;
2138 int nbOfCells=getNumberOfCells();
2139 const int *conn=getNodalConnectivity()->getConstPointer();
2140 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2141 for(int i=0;i<nbOfCells;i++)
2143 int ref=0,nbOfHit=0;
2144 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2148 if(fastFinder[*work2])
2151 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2152 cellIdsKept->pushBackSilent(i);
2154 cellIdsKeptArr=cellIdsKept.retn();
2158 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2159 * this->getMeshDimension(), that bound some cells of \a this mesh.
2160 * The cells of lower dimension to include to the result mesh are selected basing on
2161 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2162 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2163 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2164 * created mesh shares the node coordinates array with \a this mesh.
2165 * \param [in] begin - the array of node ids.
2166 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2167 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2168 * array \a begin are added, else cells whose any node is in the
2169 * array \a begin are added.
2170 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2171 * to delete this mesh using decrRef() as it is no more needed.
2172 * \throw If the coordinates array is not set.
2173 * \throw If the nodal connectivity of cells is not defined.
2174 * \throw If any node id in \a begin is not valid.
2176 * \if ENABLE_EXAMPLES
2177 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2178 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2181 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2184 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2185 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2186 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2187 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2191 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2192 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2193 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2194 * array of \a this mesh, else "free" nodes are removed from the result mesh
2195 * by calling zipCoords().
2196 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2197 * to delete this mesh using decrRef() as it is no more needed.
2198 * \throw If the coordinates array is not set.
2199 * \throw If the nodal connectivity of cells is not defined.
2201 * \if ENABLE_EXAMPLES
2202 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2203 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2206 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2208 DataArrayInt *desc=DataArrayInt::New();
2209 DataArrayInt *descIndx=DataArrayInt::New();
2210 DataArrayInt *revDesc=DataArrayInt::New();
2211 DataArrayInt *revDescIndx=DataArrayInt::New();
2213 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2216 descIndx->decrRef();
2217 int nbOfCells=meshDM1->getNumberOfCells();
2218 const int *revDescIndxC=revDescIndx->getConstPointer();
2219 std::vector<int> boundaryCells;
2220 for(int i=0;i<nbOfCells;i++)
2221 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2222 boundaryCells.push_back(i);
2223 revDescIndx->decrRef();
2224 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2229 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2230 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2231 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2233 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2235 checkFullyDefined();
2236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2241 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2242 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2246 const int *revDescPtr=revDesc->getConstPointer();
2247 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2248 int nbOfCells=getNumberOfCells();
2249 std::vector<bool> ret1(nbOfCells,false);
2251 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2252 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2253 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2255 DataArrayInt *ret2=DataArrayInt::New();
2257 int *ret2Ptr=ret2->getPointer();
2259 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2262 ret2->setName("BoundaryCells");
2267 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2268 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2269 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2270 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2272 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2273 * This method method returns cells ids set s = s1 + s2 where :
2275 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2276 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2278 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2279 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2281 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2282 * \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
2283 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2285 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2287 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2288 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2289 checkConnectivityFullyDefined();
2290 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2291 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2292 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2297 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2298 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2299 DataArrayInt *idsOtherInConsti=0;
2300 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2303 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2305 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2306 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2309 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2310 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2312 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2313 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2314 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2315 neighThisPartAuto=0;
2316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2317 const int li[2]={0,1};
2318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2319 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2323 cellIdsRk0=s0arr.retn();
2324 cellIdsRk1=s_renum1.retn();
2328 * 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
2329 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2331 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2333 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2340 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2341 revDesc=0; desc=0; descIndx=0;
2342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2344 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2348 * Finds nodes lying on the boundary of \a this mesh.
2349 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2350 * nodes. The caller is to delete this array using decrRef() as it is no
2352 * \throw If the coordinates array is not set.
2353 * \throw If the nodal connectivity of cells is node defined.
2355 * \if ENABLE_EXAMPLES
2356 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2357 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2360 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2362 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2363 return skin->computeFetchedNodeIds();
2366 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2369 return const_cast<MEDCouplingUMesh *>(this);
2373 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2374 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2375 * 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.
2376 * 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.
2377 * 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.
2379 * \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
2380 * parameter is altered during the call.
2381 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2382 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2383 * \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.
2385 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2387 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2388 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2390 checkFullyDefined();
2391 otherDimM1OnSameCoords.checkFullyDefined();
2392 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2393 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2394 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2396 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2397 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2400 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2405 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2407 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2409 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2410 DataArrayInt *idsTmp=0;
2411 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2415 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2416 DataArrayInt *tmp0=0,*tmp1=0;
2417 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2422 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2423 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2425 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2426 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2427 nodeIdsToDuplicate=s3.retn();
2431 * This method operates a modification of the connectivity and coords in \b this.
2432 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2433 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2434 * 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
2435 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2436 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2438 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2440 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2441 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2443 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2445 int nbOfNodes=getNumberOfNodes();
2446 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2447 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2451 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2452 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2453 * This method is a generalization of shiftNodeNumbersInConn().
2454 * \warning This method performs no check of validity of new ids. **Use it with care !**
2455 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2456 * this->getNumberOfNodes(), in "Old to New" mode.
2457 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2458 * \throw If the nodal connectivity of cells is not defined.
2460 * \if ENABLE_EXAMPLES
2461 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2462 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2465 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2467 checkConnectivityFullyDefined();
2468 int *conn=getNodalConnectivity()->getPointer();
2469 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2470 int nbOfCells=getNumberOfCells();
2471 for(int i=0;i<nbOfCells;i++)
2472 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2474 int& node=conn[iconn];
2475 if(node>=0)//avoid polyhedron separator
2477 node=newNodeNumbersO2N[node];
2480 _nodal_connec->declareAsNew();
2485 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2486 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2487 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2489 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2491 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2493 checkConnectivityFullyDefined();
2494 int *conn=getNodalConnectivity()->getPointer();
2495 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2496 int nbOfCells=getNumberOfCells();
2497 for(int i=0;i<nbOfCells;i++)
2498 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2500 int& node=conn[iconn];
2501 if(node>=0)//avoid polyhedron separator
2506 _nodal_connec->declareAsNew();
2511 * This method operates a modification of the connectivity in \b this.
2512 * 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.
2513 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2514 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2515 * 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
2516 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2517 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2519 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2520 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2522 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2523 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2524 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2526 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2528 checkConnectivityFullyDefined();
2529 std::map<int,int> m;
2531 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2533 int *conn=getNodalConnectivity()->getPointer();
2534 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2535 int nbOfCells=getNumberOfCells();
2536 for(int i=0;i<nbOfCells;i++)
2537 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2539 int& node=conn[iconn];
2540 if(node>=0)//avoid polyhedron separator
2542 std::map<int,int>::iterator it=m.find(node);
2551 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2553 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2554 * After the call of this method the number of cells remains the same as before.
2556 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2557 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2558 * be strictly in [0;this->getNumberOfCells()).
2560 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2561 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2562 * should be contained in[0;this->getNumberOfCells()).
2564 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2566 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2568 checkConnectivityFullyDefined();
2569 int nbCells=getNumberOfCells();
2570 const int *array=old2NewBg;
2572 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2574 const int *conn=_nodal_connec->getConstPointer();
2575 const int *connI=_nodal_connec_index->getConstPointer();
2576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2577 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2578 const int *n2oPtr=n2o->begin();
2579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2580 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2581 newConn->copyStringInfoFrom(*_nodal_connec);
2582 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2583 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2584 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2586 int *newC=newConn->getPointer();
2587 int *newCI=newConnI->getPointer();
2590 for(int i=0;i<nbCells;i++)
2593 int nbOfElts=connI[pos+1]-connI[pos];
2594 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2599 setConnectivity(newConn,newConnI);
2601 free(const_cast<int *>(array));
2605 * Finds cells whose bounding boxes intersect a given bounding box.
2606 * \param [in] bbox - an array defining the bounding box via coordinates of its
2607 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2609 * \param [in] eps - a factor used to increase size of the bounding box of cell
2610 * before comparing it with \a bbox. This factor is multiplied by the maximal
2611 * extent of the bounding box of cell to produce an addition to this bounding box.
2612 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2613 * cells. The caller is to delete this array using decrRef() as it is no more
2615 * \throw If the coordinates array is not set.
2616 * \throw If the nodal connectivity of cells is not defined.
2618 * \if ENABLE_EXAMPLES
2619 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2620 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2623 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2625 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2626 if(getMeshDimension()==-1)
2628 elems->pushBackSilent(0);
2629 return elems.retn();
2631 int dim=getSpaceDimension();
2632 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2633 const int* conn = getNodalConnectivity()->getConstPointer();
2634 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2635 const double* coords = getCoords()->getConstPointer();
2636 int nbOfCells=getNumberOfCells();
2637 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2639 for (int i=0; i<dim; i++)
2641 elem_bb[i*2]=std::numeric_limits<double>::max();
2642 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2645 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2647 int node= conn[inode];
2648 if(node>=0)//avoid polyhedron separator
2650 for (int idim=0; idim<dim; idim++)
2652 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2654 elem_bb[idim*2] = coords[node*dim+idim] ;
2656 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2658 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2663 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2664 elems->pushBackSilent(ielem);
2666 return elems.retn();
2670 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2671 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2672 * added in 'elems' parameter.
2674 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2677 if(getMeshDimension()==-1)
2679 elems->pushBackSilent(0);
2680 return elems.retn();
2682 int dim=getSpaceDimension();
2683 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2684 const int* conn = getNodalConnectivity()->getConstPointer();
2685 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2686 const double* coords = getCoords()->getConstPointer();
2687 int nbOfCells=getNumberOfCells();
2688 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2690 for (int i=0; i<dim; i++)
2692 elem_bb[i*2]=std::numeric_limits<double>::max();
2693 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2696 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2698 int node= conn[inode];
2699 if(node>=0)//avoid polyhedron separator
2701 for (int idim=0; idim<dim; idim++)
2703 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2705 elem_bb[idim*2] = coords[node*dim+idim] ;
2707 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2709 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2714 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2715 elems->pushBackSilent(ielem);
2717 return elems.retn();
2721 * Returns a type of a cell by its id.
2722 * \param [in] cellId - the id of the cell of interest.
2723 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2724 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2726 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2728 const int *ptI=_nodal_connec_index->getConstPointer();
2729 const int *pt=_nodal_connec->getConstPointer();
2730 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2731 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2734 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2735 throw INTERP_KERNEL::Exception(oss.str().c_str());
2740 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2741 * This method does not throw exception if geometric type \a type is not in \a this.
2742 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2743 * The coordinates array is not considered here.
2745 * \param [in] type the geometric type
2746 * \return cell ids in this having geometric type \a type.
2748 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2753 checkConnectivityFullyDefined();
2754 int nbCells=getNumberOfCells();
2755 int mdim=getMeshDimension();
2756 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2757 if(mdim!=(int)cm.getDimension())
2758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2759 const int *ptI=_nodal_connec_index->getConstPointer();
2760 const int *pt=_nodal_connec->getConstPointer();
2761 for(int i=0;i<nbCells;i++)
2763 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2764 ret->pushBackSilent(i);
2770 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2772 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2774 const int *ptI=_nodal_connec_index->getConstPointer();
2775 const int *pt=_nodal_connec->getConstPointer();
2776 int nbOfCells=getNumberOfCells();
2778 for(int i=0;i<nbOfCells;i++)
2779 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2785 * Returns the nodal connectivity of a given cell.
2786 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2787 * all returned node ids can be used in getCoordinatesOfNode().
2788 * \param [in] cellId - an id of the cell of interest.
2789 * \param [in,out] conn - a vector where the node ids are appended. It is not
2790 * cleared before the appending.
2791 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2793 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2795 const int *ptI=_nodal_connec_index->getConstPointer();
2796 const int *pt=_nodal_connec->getConstPointer();
2797 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2802 std::string MEDCouplingUMesh::simpleRepr() const
2804 static const char msg0[]="No coordinates specified !";
2805 std::ostringstream ret;
2806 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2807 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2809 double tt=getTime(tmpp1,tmpp2);
2810 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2811 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2813 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2815 { ret << " Mesh dimension has not been set or is invalid !"; }
2818 const int spaceDim=getSpaceDimension();
2819 ret << spaceDim << "\nInfo attached on space dimension : ";
2820 for(int i=0;i<spaceDim;i++)
2821 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2825 ret << msg0 << "\n";
2826 ret << "Number of nodes : ";
2828 ret << getNumberOfNodes() << "\n";
2830 ret << msg0 << "\n";
2831 ret << "Number of cells : ";
2832 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2833 ret << getNumberOfCells() << "\n";
2835 ret << "No connectivity specified !" << "\n";
2836 ret << "Cell types present : ";
2837 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2839 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2840 ret << cm.getRepr() << " ";
2846 std::string MEDCouplingUMesh::advancedRepr() const
2848 std::ostringstream ret;
2849 ret << simpleRepr();
2850 ret << "\nCoordinates array : \n___________________\n\n";
2852 _coords->reprWithoutNameStream(ret);
2854 ret << "No array set !\n";
2855 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2856 reprConnectivityOfThisLL(ret);
2861 * This method returns a C++ code that is a dump of \a this.
2862 * This method will throw if this is not fully defined.
2864 std::string MEDCouplingUMesh::cppRepr() const
2866 static const char coordsName[]="coords";
2867 static const char connName[]="conn";
2868 static const char connIName[]="connI";
2869 checkFullyDefined();
2870 std::ostringstream ret; ret << "// coordinates" << std::endl;
2871 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2872 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2873 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2874 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2875 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2876 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2877 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2881 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2883 std::ostringstream ret;
2884 reprConnectivityOfThisLL(ret);
2889 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2890 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2891 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2894 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2895 * 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
2896 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2898 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2900 int mdim=getMeshDimension();
2902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2903 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2905 bool needToCpyCT=true;
2908 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2916 if(!_nodal_connec_index)
2918 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2923 tmp2=_nodal_connec_index;
2926 ret->setConnectivity(tmp1,tmp2,false);
2931 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2932 ret->setCoords(coords);
2935 ret->setCoords(_coords);
2939 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2941 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2943 int nbOfCells=getNumberOfCells();
2944 const int *c=_nodal_connec->getConstPointer();
2945 const int *ci=_nodal_connec_index->getConstPointer();
2946 for(int i=0;i<nbOfCells;i++)
2948 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2949 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2950 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2955 stream << "Connectivity not defined !\n";
2958 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2960 const int *ptI=_nodal_connec_index->getConstPointer();
2961 const int *pt=_nodal_connec->getConstPointer();
2962 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2963 return ptI[cellId+1]-ptI[cellId]-1;
2965 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2969 * Returns types of cells of the specified part of \a this mesh.
2970 * This method avoids computing sub-mesh explicitely to get its types.
2971 * \param [in] begin - an array of cell ids of interest.
2972 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2973 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2974 * describing the cell types.
2975 * \throw If the coordinates array is not set.
2976 * \throw If the nodal connectivity of cells is not defined.
2977 * \sa getAllGeoTypes()
2979 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2981 checkFullyDefined();
2982 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2983 const int *conn=_nodal_connec->getConstPointer();
2984 const int *connIndex=_nodal_connec_index->getConstPointer();
2985 for(const int *w=begin;w!=end;w++)
2986 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2991 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2992 * a set of types of cells constituting \a this mesh.
2993 * This method is for advanced users having prepared their connectivity before. For
2994 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2995 * \param [in] conn - the nodal connectivity array.
2996 * \param [in] connIndex - the nodal connectivity index array.
2997 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3000 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3002 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3003 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3004 if(isComputingTypes)
3010 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3011 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3013 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3014 _nodal_connec(0),_nodal_connec_index(0),
3015 _types(other._types)
3017 if(other._nodal_connec)
3018 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3019 if(other._nodal_connec_index)
3020 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3023 MEDCouplingUMesh::~MEDCouplingUMesh()
3026 _nodal_connec->decrRef();
3027 if(_nodal_connec_index)
3028 _nodal_connec_index->decrRef();
3032 * Recomputes a set of cell types of \a this mesh. For more info see
3033 * \ref MEDCouplingUMeshNodalConnectivity.
3035 void MEDCouplingUMesh::computeTypes()
3037 if(_nodal_connec && _nodal_connec_index)
3040 const int *conn=_nodal_connec->getConstPointer();
3041 const int *connIndex=_nodal_connec_index->getConstPointer();
3042 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3044 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3045 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3050 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3052 void MEDCouplingUMesh::checkFullyDefined() const
3054 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3055 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3059 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3061 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3063 if(!_nodal_connec_index || !_nodal_connec)
3064 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3068 * Returns a number of cells constituting \a this mesh.
3069 * \return int - the number of cells in \a this mesh.
3070 * \throw If the nodal connectivity of cells is not defined.
3072 int MEDCouplingUMesh::getNumberOfCells() const
3074 if(_nodal_connec_index)
3075 return _nodal_connec_index->getNumberOfTuples()-1;
3080 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3084 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3085 * mesh. For more info see \ref MEDCouplingMeshesPage.
3086 * \return int - the dimension of \a this mesh.
3087 * \throw If the mesh dimension is not defined using setMeshDimension().
3089 int MEDCouplingUMesh::getMeshDimension() const
3092 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3097 * Returns a length of the nodal connectivity array.
3098 * This method is for test reason. Normally the integer returned is not useable by
3099 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3100 * \return int - the length of the nodal connectivity array.
3102 int MEDCouplingUMesh::getMeshLength() const
3104 return _nodal_connec->getNbOfElems();
3108 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3110 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3112 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3113 tinyInfo.push_back(getMeshDimension());
3114 tinyInfo.push_back(getNumberOfCells());
3116 tinyInfo.push_back(getMeshLength());
3118 tinyInfo.push_back(-1);
3122 * First step of unserialization process.
3124 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3126 return tinyInfo[6]<=0;
3130 * Second step of serialization process.
3131 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3133 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3135 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3137 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3141 * Third and final step of serialization process.
3143 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3145 MEDCouplingPointSet::serialize(a1,a2);
3146 if(getMeshDimension()>-1)
3148 a1=DataArrayInt::New();
3149 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3150 int *ptA1=a1->getPointer();
3151 const int *conn=getNodalConnectivity()->getConstPointer();
3152 const int *index=getNodalConnectivityIndex()->getConstPointer();
3153 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3154 std::copy(conn,conn+getMeshLength(),ptA1);
3161 * Second and final unserialization process.
3162 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3164 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3166 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3167 setMeshDimension(tinyInfo[5]);
3171 const int *recvBuffer=a1->getConstPointer();
3172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3173 myConnecIndex->alloc(tinyInfo[6]+1,1);
3174 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3176 myConnec->alloc(tinyInfo[7],1);
3177 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3178 setConnectivity(myConnec, myConnecIndex);
3183 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3184 * CellIds are given using range specified by a start an end and step.
3186 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3188 checkFullyDefined();
3189 int ncell=getNumberOfCells();
3190 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3191 ret->_mesh_dim=_mesh_dim;
3192 ret->setCoords(_coords);
3193 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3195 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3197 const int *conn=_nodal_connec->getConstPointer();
3198 const int *connIndex=_nodal_connec_index->getConstPointer();
3199 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3201 if(work>=0 && work<ncell)
3203 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3207 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3208 throw INTERP_KERNEL::Exception(oss.str().c_str());
3211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3212 int *newConnPtr=newConn->getPointer();
3213 std::set<INTERP_KERNEL::NormalizedCellType> types;
3215 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3217 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3218 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3220 ret->setConnectivity(newConn,newConnI,false);
3222 ret->copyTinyInfoFrom(this);
3227 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3228 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3229 * The return newly allocated mesh will share the same coordinates as \a this.
3231 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3233 checkConnectivityFullyDefined();
3234 int ncell=getNumberOfCells();
3235 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3236 ret->_mesh_dim=_mesh_dim;
3237 ret->setCoords(_coords);
3238 std::size_t nbOfElemsRet=std::distance(begin,end);
3239 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3241 const int *conn=_nodal_connec->getConstPointer();
3242 const int *connIndex=_nodal_connec_index->getConstPointer();
3244 for(const int *work=begin;work!=end;work++,newNbring++)
3246 if(*work>=0 && *work<ncell)
3247 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3251 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3252 throw INTERP_KERNEL::Exception(oss.str().c_str());
3255 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3256 int *connRetWork=connRet;
3257 std::set<INTERP_KERNEL::NormalizedCellType> types;
3258 for(const int *work=begin;work!=end;work++)
3260 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3261 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3264 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3266 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3267 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3269 ret->copyTinyInfoFrom(this);
3274 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3276 * For 1D cells, the returned field contains lengths.<br>
3277 * For 2D cells, the returned field contains areas.<br>
3278 * For 3D cells, the returned field contains volumes.
3279 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3280 * orientation, i.e. the volume is always positive.
3281 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3282 * and one time . The caller is to delete this field using decrRef() as it is no
3285 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3287 std::string name="MeasureOfMesh_";
3289 int nbelem=getNumberOfCells();
3290 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3291 field->setName(name);
3292 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3293 array->alloc(nbelem,1);
3294 double *area_vol=array->getPointer();
3295 field->setArray(array) ; array=0;
3296 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3297 field->synchronizeTimeWithMesh();
3298 if(getMeshDimension()!=-1)
3301 INTERP_KERNEL::NormalizedCellType type;
3302 int dim_space=getSpaceDimension();
3303 const double *coords=getCoords()->getConstPointer();
3304 const int *connec=getNodalConnectivity()->getConstPointer();
3305 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3306 for(int iel=0;iel<nbelem;iel++)
3308 ipt=connec_index[iel];
3309 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3310 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);
3313 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3317 area_vol[0]=std::numeric_limits<double>::max();
3319 return field.retn();
3323 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3325 * For 1D cells, the returned array contains lengths.<br>
3326 * For 2D cells, the returned array contains areas.<br>
3327 * For 3D cells, the returned array contains volumes.
3328 * This method avoids building explicitly a part of \a this mesh to perform the work.
3329 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3330 * orientation, i.e. the volume is always positive.
3331 * \param [in] begin - an array of cell ids of interest.
3332 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3333 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3334 * delete this array using decrRef() as it is no more needed.
3336 * \if ENABLE_EXAMPLES
3337 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3338 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3340 * \sa getMeasureField()
3342 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3344 std::string name="PartMeasureOfMesh_";
3346 int nbelem=(int)std::distance(begin,end);
3347 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3348 array->setName(name);
3349 array->alloc(nbelem,1);
3350 double *area_vol=array->getPointer();
3351 if(getMeshDimension()!=-1)
3354 INTERP_KERNEL::NormalizedCellType type;
3355 int dim_space=getSpaceDimension();
3356 const double *coords=getCoords()->getConstPointer();
3357 const int *connec=getNodalConnectivity()->getConstPointer();
3358 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3359 for(const int *iel=begin;iel!=end;iel++)
3361 ipt=connec_index[*iel];
3362 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3363 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3366 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3370 area_vol[0]=std::numeric_limits<double>::max();
3372 return array.retn();
3376 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3377 * \a this one. The returned field contains the dual cell volume for each corresponding
3378 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3379 * the dual mesh in P1 sens of \a this.<br>
3380 * For 1D cells, the returned field contains lengths.<br>
3381 * For 2D cells, the returned field contains areas.<br>
3382 * For 3D cells, the returned field contains volumes.
3383 * This method is useful to check "P1*" conservative interpolators.
3384 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3385 * orientation, i.e. the volume is always positive.
3386 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3387 * nodes and one time. The caller is to delete this array using decrRef() as
3388 * it is no more needed.
3390 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3393 std::string name="MeasureOnNodeOfMesh_";
3395 int nbNodes=getNumberOfNodes();
3396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3397 double cst=1./((double)getMeshDimension()+1.);
3398 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3399 array->alloc(nbNodes,1);
3400 double *valsToFill=array->getPointer();
3401 std::fill(valsToFill,valsToFill+nbNodes,0.);
3402 const double *values=tmp->getArray()->getConstPointer();
3403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3405 getReverseNodalConnectivity(da,daInd);
3406 const int *daPtr=da->getConstPointer();
3407 const int *daIPtr=daInd->getConstPointer();
3408 for(int i=0;i<nbNodes;i++)
3409 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3410 valsToFill[i]+=cst*values[*cell];
3412 ret->setArray(array);
3417 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3418 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3419 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3420 * and are normalized.
3421 * <br> \a this can be either
3422 * - a 2D mesh in 2D or 3D space or
3423 * - an 1D mesh in 2D space.
3425 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3426 * cells and one time. The caller is to delete this field using decrRef() as
3427 * it is no more needed.
3428 * \throw If the nodal connectivity of cells is not defined.
3429 * \throw If the coordinates array is not set.
3430 * \throw If the mesh dimension is not set.
3431 * \throw If the mesh and space dimension is not as specified above.
3433 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3435 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3436 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3437 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3438 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3439 int nbOfCells=getNumberOfCells();
3440 int nbComp=getMeshDimension()+1;
3441 array->alloc(nbOfCells,nbComp);
3442 double *vals=array->getPointer();
3443 const int *connI=_nodal_connec_index->getConstPointer();
3444 const int *conn=_nodal_connec->getConstPointer();
3445 const double *coords=_coords->getConstPointer();
3446 if(getMeshDimension()==2)
3448 if(getSpaceDimension()==3)
3450 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3451 const double *locPtr=loc->getConstPointer();
3452 for(int i=0;i<nbOfCells;i++,vals+=3)
3454 int offset=connI[i];
3455 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3456 double n=INTERP_KERNEL::norm<3>(vals);
3457 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3462 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3463 const double *isAbsPtr=isAbs->getArray()->begin();
3464 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3465 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3468 else//meshdimension==1
3471 for(int i=0;i<nbOfCells;i++)
3473 int offset=connI[i];
3474 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3475 double n=INTERP_KERNEL::norm<2>(tmp);
3476 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3481 ret->setArray(array);
3483 ret->synchronizeTimeWithSupport();
3488 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3489 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3490 * and are normalized.
3491 * <br> \a this can be either
3492 * - a 2D mesh in 2D or 3D space or
3493 * - an 1D mesh in 2D space.
3495 * This method avoids building explicitly a part of \a this mesh to perform the work.
3496 * \param [in] begin - an array of cell ids of interest.
3497 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3498 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499 * cells and one time. The caller is to delete this field using decrRef() as
3500 * it is no more needed.
3501 * \throw If the nodal connectivity of cells is not defined.
3502 * \throw If the coordinates array is not set.
3503 * \throw If the mesh dimension is not set.
3504 * \throw If the mesh and space dimension is not as specified above.
3505 * \sa buildOrthogonalField()
3507 * \if ENABLE_EXAMPLES
3508 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3509 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3512 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3514 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3515 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3516 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3517 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3518 std::size_t nbelems=std::distance(begin,end);
3519 int nbComp=getMeshDimension()+1;
3520 array->alloc((int)nbelems,nbComp);
3521 double *vals=array->getPointer();
3522 const int *connI=_nodal_connec_index->getConstPointer();
3523 const int *conn=_nodal_connec->getConstPointer();
3524 const double *coords=_coords->getConstPointer();
3525 if(getMeshDimension()==2)
3527 if(getSpaceDimension()==3)
3529 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3530 const double *locPtr=loc->getConstPointer();
3531 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3533 int offset=connI[*i];
3534 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3535 double n=INTERP_KERNEL::norm<3>(vals);
3536 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3541 for(std::size_t i=0;i<nbelems;i++)
3542 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3545 else//meshdimension==1
3548 for(const int *i=begin;i!=end;i++)
3550 int offset=connI[*i];
3551 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3552 double n=INTERP_KERNEL::norm<2>(tmp);
3553 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3558 ret->setArray(array);
3560 ret->synchronizeTimeWithSupport();
3565 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3566 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3567 * and are \b not normalized.
3568 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3569 * cells and one time. The caller is to delete this field using decrRef() as
3570 * it is no more needed.
3571 * \throw If the nodal connectivity of cells is not defined.
3572 * \throw If the coordinates array is not set.
3573 * \throw If \a this->getMeshDimension() != 1.
3574 * \throw If \a this mesh includes cells of type other than SEG2.
3576 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3578 if(getMeshDimension()!=1)
3579 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3580 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3581 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3582 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3583 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3584 int nbOfCells=getNumberOfCells();
3585 int spaceDim=getSpaceDimension();
3586 array->alloc(nbOfCells,spaceDim);
3587 double *pt=array->getPointer();
3588 const double *coo=getCoords()->getConstPointer();
3589 std::vector<int> conn;
3591 for(int i=0;i<nbOfCells;i++)
3594 getNodeIdsOfCell(i,conn);
3595 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3597 ret->setArray(array);
3599 ret->synchronizeTimeWithSupport();
3604 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3605 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3606 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3607 * from. If a result face is shared by two 3D cells, then the face in included twice in
3609 * \param [in] origin - 3 components of a point defining location of the plane.
3610 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3611 * must be greater than 1e-6.
3612 * \param [in] eps - half-thickness of the plane.
3613 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3614 * producing correspondent 2D cells. The caller is to delete this array
3615 * using decrRef() as it is no more needed.
3616 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3617 * not share the node coordinates array with \a this mesh. The caller is to
3618 * delete this mesh using decrRef() as it is no more needed.
3619 * \throw If the coordinates array is not set.
3620 * \throw If the nodal connectivity of cells is not defined.
3621 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3622 * \throw If magnitude of \a vec is less than 1e-6.
3623 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3624 * \throw If \a this includes quadratic cells.
3626 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3628 checkFullyDefined();
3629 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3632 if(candidates->empty())
3633 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3634 std::vector<int> nodes;
3635 DataArrayInt *cellIds1D=0;
3636 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3637 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3642 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3643 revDesc2=0; revDescIndx2=0;
3644 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3645 revDesc1=0; revDescIndx1=0;
3646 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3649 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3650 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3652 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3653 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3654 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3655 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3656 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3658 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3659 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3660 if(cellIds2->empty())
3661 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3663 ret->setCoords(mDesc1->getCoords());
3664 ret->setConnectivity(conn,connI,true);
3665 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3670 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3671 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
3672 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3674 * \param [in] origin - 3 components of a point defining location of the plane.
3675 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3676 * must be greater than 1e-6.
3677 * \param [in] eps - half-thickness of the plane.
3678 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3679 * producing correspondent segments. The caller is to delete this array
3680 * using decrRef() as it is no more needed.
3681 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3682 * mesh in 3D space. This mesh does not share the node coordinates array with
3683 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3685 * \throw If the coordinates array is not set.
3686 * \throw If the nodal connectivity of cells is not defined.
3687 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3688 * \throw If magnitude of \a vec is less than 1e-6.
3689 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3690 * \throw If \a this includes quadratic cells.
3692 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3694 checkFullyDefined();
3695 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3696 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3698 if(candidates->empty())
3699 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3700 std::vector<int> nodes;
3701 DataArrayInt *cellIds1D=0;
3702 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3703 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3706 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3707 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3708 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3709 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3712 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3713 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3715 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3716 int ncellsSub=subMesh->getNumberOfCells();
3717 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3718 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3719 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3720 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3723 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3724 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3725 for(int i=0;i<ncellsSub;i++)
3727 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3729 if(cut3DSurf[i].first!=-2)
3731 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3732 connI->pushBackSilent(conn->getNumberOfTuples());
3733 cellIds2->pushBackSilent(i);
3737 int cellId3DSurf=cut3DSurf[i].second;
3738 int offset=nodalI[cellId3DSurf]+1;
3739 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3740 for(int j=0;j<nbOfEdges;j++)
3742 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3743 connI->pushBackSilent(conn->getNumberOfTuples());
3744 cellIds2->pushBackSilent(cellId3DSurf);
3749 if(cellIds2->empty())
3750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3751 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3752 ret->setCoords(mDesc1->getCoords());
3753 ret->setConnectivity(conn,connI,true);
3754 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3759 * Finds cells whose bounding boxes intersect a given plane.
3760 * \param [in] origin - 3 components of a point defining location of the plane.
3761 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3762 * must be greater than 1e-6.
3763 * \param [in] eps - half-thickness of the plane.
3764 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3765 * cells. The caller is to delete this array using decrRef() as it is no more
3767 * \throw If the coordinates array is not set.
3768 * \throw If the nodal connectivity of cells is not defined.
3769 * \throw If \a this->getSpaceDimension() != 3.
3770 * \throw If magnitude of \a vec is less than 1e-6.
3771 * \sa buildSlice3D()
3773 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3775 checkFullyDefined();
3776 if(getSpaceDimension()!=3)
3777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3778 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3780 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3782 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3783 double angle=acos(vec[2]/normm);
3784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3788 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3789 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3790 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3792 mw->getBoundingBox(bbox);
3793 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3794 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3798 getBoundingBox(bbox);
3799 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3800 cellIds=getCellsInBoundingBox(bbox,eps);
3802 return cellIds.retn();
3806 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3807 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3808 * No consideration of coordinate is done by this method.
3809 * 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)
3810 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3812 bool MEDCouplingUMesh::isContiguous1D() const
3814 if(getMeshDimension()!=1)
3815 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3816 int nbCells=getNumberOfCells();
3818 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3819 const int *connI=_nodal_connec_index->getConstPointer();
3820 const int *conn=_nodal_connec->getConstPointer();
3821 int ref=conn[connI[0]+2];
3822 for(int i=1;i<nbCells;i++)
3824 if(conn[connI[i]+1]!=ref)
3826 ref=conn[connI[i]+2];
3832 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3833 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3834 * \param pt reference point of the line
3835 * \param v normalized director vector of the line
3836 * \param eps max precision before throwing an exception
3837 * \param res output of size this->getNumberOfCells
3839 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3841 if(getMeshDimension()!=1)
3842 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3843 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3844 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3845 if(getSpaceDimension()!=3)
3846 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3847 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3848 const double *fPtr=f->getArray()->getConstPointer();
3850 for(int i=0;i<getNumberOfCells();i++)
3852 const double *tmp1=fPtr+3*i;
3853 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3854 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3855 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3856 double n1=INTERP_KERNEL::norm<3>(tmp);
3857 n1/=INTERP_KERNEL::norm<3>(tmp1);
3859 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3861 const double *coo=getCoords()->getConstPointer();
3862 for(int i=0;i<getNumberOfNodes();i++)
3864 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3865 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3866 res[i]=std::accumulate(tmp,tmp+3,0.);
3871 * 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.
3872 * \a this is expected to be a mesh so that its space dimension is equal to its
3873 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3874 * 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).
3876 * 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
3877 * 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).
3878 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3880 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3881 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3883 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3884 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3885 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3886 * \return the positive value of the distance.
3887 * \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
3889 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3891 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3893 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3894 if(meshDim!=spaceDim-1)
3895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3896 if(meshDim!=2 && meshDim!=1)
3897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3898 checkFullyDefined();
3899 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3900 { 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()); }
3901 DataArrayInt *ret1=0;
3902 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3903 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3905 cellId=*ret1Safe->begin();
3906 return *ret0->begin();
3910 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3911 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3912 * 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
3913 * 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).
3914 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3916 * \a this is expected to be a mesh so that its space dimension is equal to its
3917 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3918 * 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).
3920 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3921 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3923 * \param [in] pts the list of points in which each tuple represents a point
3924 * \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.
3925 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3926 * \throw if number of components of \a pts is not equal to the space dimension.
3927 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3928 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3930 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3933 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3934 pts->checkAllocated();
3935 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3936 if(meshDim!=spaceDim-1)
3937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3938 if(meshDim!=2 && meshDim!=1)
3939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3940 if(pts->getNumberOfComponents()!=spaceDim)
3942 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3943 throw INTERP_KERNEL::Exception(oss.str().c_str());
3945 checkFullyDefined();
3946 int nbCells=getNumberOfCells();
3948 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3949 int nbOfPts=pts->getNumberOfTuples();
3950 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3952 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3953 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3954 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3955 const double *bbox(bboxArr->begin());
3960 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3961 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3963 double x=std::numeric_limits<double>::max();
3964 std::vector<int> elems;
3965 myTree.getMinDistanceOfMax(ptsPtr,x);
3966 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3967 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3973 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3974 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3976 double x=std::numeric_limits<double>::max();
3977 std::vector<int> elems;
3978 myTree.getMinDistanceOfMax(ptsPtr,x);
3979 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3980 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3987 cellIds=ret1.retn();
3992 * \param [in] pt the start pointer (included) of the coordinates of the point
3993 * \param [in] cellIdsBg the start pointer (included) of cellIds
3994 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3995 * \param [in] nc nodal connectivity
3996 * \param [in] ncI nodal connectivity index
3997 * \param [in,out] ret0 the min distance between \a this and the external input point
3998 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4001 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)
4004 ret0=std::numeric_limits<double>::max();
4005 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4007 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4009 case INTERP_KERNEL::NORM_TRI3:
4011 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4013 { ret0=tmp; cellId=*zeCell; }
4016 case INTERP_KERNEL::NORM_QUAD4:
4017 case INTERP_KERNEL::NORM_POLYGON:
4019 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4021 { ret0=tmp; cellId=*zeCell; }
4025 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4031 * \param [in] pt the start pointer (included) of the coordinates of the point
4032 * \param [in] cellIdsBg the start pointer (included) of cellIds
4033 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4034 * \param [in] nc nodal connectivity
4035 * \param [in] ncI nodal connectivity index
4036 * \param [in,out] ret0 the min distance between \a this and the external input point
4037 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4038 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4040 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)
4043 ret0=std::numeric_limits<double>::max();
4044 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4046 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4048 case INTERP_KERNEL::NORM_SEG2:
4050 std::size_t uselessEntry=0;
4051 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4054 { ret0=tmp; cellId=*zeCell; }
4058 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4064 * Finds cells in contact with a ball (i.e. a point with precision).
4065 * 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.
4066 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4068 * \warning This method is suitable if the caller intends to evaluate only one
4069 * point, for more points getCellsContainingPoints() is recommended as it is
4071 * \param [in] pos - array of coordinates of the ball central point.
4072 * \param [in] eps - ball radius.
4073 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4074 * if there are no such cells.
4075 * \throw If the coordinates array is not set.
4076 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4078 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4080 std::vector<int> elts;
4081 getCellsContainingPoint(pos,eps,elts);
4084 return elts.front();
4088 * Finds cells in contact with a ball (i.e. a point with precision).
4089 * 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.
4090 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4091 * \warning This method is suitable if the caller intends to evaluate only one
4092 * point, for more points getCellsContainingPoints() is recommended as it is
4094 * \param [in] pos - array of coordinates of the ball central point.
4095 * \param [in] eps - ball radius.
4096 * \param [out] elts - vector returning ids of the found cells. It is cleared
4097 * before inserting ids.
4098 * \throw If the coordinates array is not set.
4099 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4101 * \if ENABLE_EXAMPLES
4102 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4103 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4106 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4109 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4110 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4115 namespace ParaMEDMEM
4117 template<const int SPACEDIMM>
4121 static const int MY_SPACEDIM=SPACEDIMM;
4122 static const int MY_MESHDIM=8;
4123 typedef int MyConnType;
4124 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4126 // useless, but for windows compilation ...
4127 const double* getCoordinatesPtr() const { return 0; }
4128 const int* getConnectivityPtr() const { return 0; }
4129 const int* getConnectivityIndexPtr() const { return 0; }
4130 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4135 * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4137 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4139 INTERP_KERNEL::Edge *ret=0;
4140 INTERP_KERNEL::Node *n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),*n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4141 m[n0]=bg[0]; m[n1]=bg[1];
4144 case INTERP_KERNEL::NORM_SEG2:
4146 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4149 case INTERP_KERNEL::NORM_SEG3:
4151 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4152 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4153 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4154 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4155 bool colinearity(inters.areColinears());
4156 delete e1; delete e2;
4158 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4160 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4164 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4169 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4171 INTERP_KERNEL::Edge *ret=0;
4174 case INTERP_KERNEL::NORM_SEG2:
4176 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4179 case INTERP_KERNEL::NORM_SEG3:
4181 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4182 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4183 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4184 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4185 bool colinearity=inters.areColinears();
4186 delete e1; delete e2;
4188 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4190 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4191 mapp2[bg[2]].second=false;
4195 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4201 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4202 * the global mesh 'mDesc'.
4203 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4204 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4206 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4207 std::map<INTERP_KERNEL::Node *,int>& mapp)
4208 throw(INTERP_KERNEL::Exception)
4211 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.
4212 const double *coo=mDesc->getCoords()->getConstPointer();
4213 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4214 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4216 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4217 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4218 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4220 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4221 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4223 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4224 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4226 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4227 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4229 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4231 if((*it2).second.second)
4232 mapp[(*it2).second.first]=(*it2).first;
4233 ((*it2).second.first)->decrRef();
4238 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4242 int locId=nodeId-offset2;
4243 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4247 int locId=nodeId-offset1;
4248 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4250 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4254 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4256 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4257 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4258 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4260 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4262 int eltId1=abs(*desc1)-1;
4263 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4265 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4266 if(it==mappRev.end())
4268 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4279 template<int SPACEDIM>
4280 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4281 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4283 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4284 int *eltsIndexPtr(eltsIndex->getPointer());
4285 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4286 const double *bbox(bboxArr->begin());
4287 int nbOfCells=getNumberOfCells();
4288 const int *conn=_nodal_connec->getConstPointer();
4289 const int *connI=_nodal_connec_index->getConstPointer();
4290 double bb[2*SPACEDIM];
4291 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4292 for(int i=0;i<nbOfPoints;i++)
4294 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4295 for(int j=0;j<SPACEDIM;j++)
4297 bb[2*j]=pos[SPACEDIM*i+j];
4298 bb[2*j+1]=pos[SPACEDIM*i+j];
4300 std::vector<int> candidates;
4301 myTree.getIntersectingElems(bb,candidates);
4302 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4304 int sz(connI[(*iter)+1]-connI[*iter]-1);
4305 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4307 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4308 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4313 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4314 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4315 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4316 INTERP_KERNEL::QuadraticPolygon *pol(0);
4317 for(int j=0;j<sz;j++)
4319 int nodeId(conn[connI[*iter]+1+j]);
4320 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4322 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4323 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4325 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4326 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4327 double a(0.),b(0.),c(0.);
4328 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4329 status=pol->isInOrOut2(n);
4330 delete pol; n->decrRef();
4334 eltsIndexPtr[i+1]++;
4335 elts->pushBackSilent(*iter);
4341 * Finds cells in contact with several balls (i.e. points with precision).
4342 * This method is an extension of getCellContainingPoint() and
4343 * getCellsContainingPoint() for the case of multiple points.
4344 * 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.
4345 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4346 * \param [in] pos - an array of coordinates of points in full interlace mode :
4347 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4348 * this->getSpaceDimension() * \a nbOfPoints
4349 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4350 * \param [in] eps - radius of balls (i.e. the precision).
4351 * \param [out] elts - vector returning ids of found cells.
4352 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4353 * dividing cell ids in \a elts into groups each referring to one
4354 * point. Its every element (except the last one) is an index pointing to the
4355 * first id of a group of cells. For example cells in contact with the *i*-th
4356 * point are described by following range of indices:
4357 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4358 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4359 * Number of cells in contact with the *i*-th point is
4360 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4361 * \throw If the coordinates array is not set.
4362 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4364 * \if ENABLE_EXAMPLES
4365 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4366 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4369 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4372 int spaceDim=getSpaceDimension();
4373 int mDim=getMeshDimension();
4378 const double *coords=_coords->getConstPointer();
4379 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4386 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4388 else if(spaceDim==2)
4392 const double *coords=_coords->getConstPointer();
4393 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4396 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4398 else if(spaceDim==1)
4402 const double *coords=_coords->getConstPointer();
4403 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4406 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4409 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4413 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4414 * least two its edges intersect each other anywhere except their extremities. An
4415 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4416 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4417 * cleared before filling in.
4418 * \param [in] eps - precision.
4419 * \throw If \a this->getMeshDimension() != 2.
4420 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4422 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4424 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4425 if(getMeshDimension()!=2)
4426 throw INTERP_KERNEL::Exception(msg);
4427 int spaceDim=getSpaceDimension();
4428 if(spaceDim!=2 && spaceDim!=3)
4429 throw INTERP_KERNEL::Exception(msg);
4430 const int *conn=_nodal_connec->getConstPointer();
4431 const int *connI=_nodal_connec_index->getConstPointer();
4432 int nbOfCells=getNumberOfCells();
4433 std::vector<double> cell2DinS2;
4434 for(int i=0;i<nbOfCells;i++)
4436 int offset=connI[i];
4437 int nbOfNodesForCell=connI[i+1]-offset-1;
4438 if(nbOfNodesForCell<=3)
4440 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4441 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4442 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4449 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4451 * 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.
4452 * 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.
4454 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4455 * This convex envelop is computed using Jarvis march algorithm.
4456 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4457 * 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)
4458 * 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.
4460 * \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.
4461 * \sa MEDCouplingUMesh::colinearize2D
4463 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4465 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4467 checkFullyDefined();
4468 const double *coords=getCoords()->getConstPointer();
4469 int nbOfCells=getNumberOfCells();
4470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4471 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4473 int *workIndexOut=nodalConnecIndexOut->getPointer();
4475 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4476 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4477 std::set<INTERP_KERNEL::NormalizedCellType> types;
4478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4479 isChanged->alloc(0,1);
4480 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4482 int pos=nodalConnecOut->getNumberOfTuples();
4483 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4484 isChanged->pushBackSilent(i);
4485 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4486 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4488 if(isChanged->empty())
4490 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4492 return isChanged.retn();
4496 * This method is \b NOT const because it can modify \a this.
4497 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4498 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4499 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4500 * \b 1 for translation and rotation around point of 'mesh1D'.
4501 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4503 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4505 checkFullyDefined();
4506 mesh1D->checkFullyDefined();
4507 if(!mesh1D->isContiguous1D())
4508 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4509 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4510 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4511 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4512 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4513 if(mesh1D->getMeshDimension()!=1)
4514 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4516 if(isPresenceOfQuadratic())
4518 if(mesh1D->isFullyQuadratic())
4521 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4524 int oldNbOfNodes=getNumberOfNodes();
4525 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4530 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4535 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4539 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4541 setCoords(newCoords);
4542 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4548 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4549 * If it is not the case an exception will be thrown.
4550 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4551 * intersection of plane defined by ('origin','vec').
4552 * This method has one in/out parameter : 'cut3DCurve'.
4553 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4554 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4555 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4556 * This method will throw an exception if \a this contains a non linear segment.
4558 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4560 checkFullyDefined();
4561 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4562 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4563 int ncells=getNumberOfCells();
4564 int nnodes=getNumberOfNodes();
4565 double vec2[3],vec3[3],vec4[3];
4566 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4568 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4569 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4570 const int *conn=_nodal_connec->getConstPointer();
4571 const int *connI=_nodal_connec_index->getConstPointer();
4572 const double *coo=_coords->getConstPointer();
4573 std::vector<double> addCoo;
4574 for(int i=0;i<ncells;i++)
4576 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4578 if(cut3DCurve[i]==-2)
4580 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4581 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];
4582 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4583 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4584 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4586 const double *st2=coo+3*st;
4587 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4588 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]));
4589 if(pos>eps && pos<1-eps)
4591 int nNode=((int)addCoo.size())/3;
4592 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4593 addCoo.insert(addCoo.end(),vec4,vec4+3);
4594 cut3DCurve[i]=nnodes+nNode;
4600 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4604 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4605 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4606 coo2->alloc(newNbOfNodes,3);
4607 double *tmp=coo2->getPointer();
4608 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4609 std::copy(addCoo.begin(),addCoo.end(),tmp);
4610 DataArrayDouble::SetArrayIn(coo2,_coords);
4615 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4616 * \param mesh1D is the input 1D mesh used for translation computation.
4617 * \return newCoords new coords filled by this method.
4619 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4621 int oldNbOfNodes=getNumberOfNodes();
4622 int nbOf1DCells=mesh1D->getNumberOfCells();
4623 int spaceDim=getSpaceDimension();
4624 DataArrayDouble *ret=DataArrayDouble::New();
4625 std::vector<bool> isQuads;
4626 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4627 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4628 double *retPtr=ret->getPointer();
4629 const double *coords=getCoords()->getConstPointer();
4630 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4632 std::vector<double> c;
4636 for(int i=0;i<nbOf1DCells;i++)
4639 mesh1D->getNodeIdsOfCell(i,v);
4641 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4642 mesh1D->getCoordinatesOfNode(v[0],c);
4643 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4644 for(int j=0;j<oldNbOfNodes;j++)
4645 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4649 mesh1D->getCoordinatesOfNode(v[1],c);
4650 mesh1D->getCoordinatesOfNode(v[0],c);
4651 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4652 for(int j=0;j<oldNbOfNodes;j++)
4653 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4656 ret->copyStringInfoFrom(*getCoords());
4661 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4662 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4663 * \return newCoords new coords filled by this method.
4665 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4667 if(mesh1D->getSpaceDimension()==2)
4668 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4669 if(mesh1D->getSpaceDimension()==3)
4670 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4671 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4675 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4676 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4677 * \return newCoords new coords filled by this method.
4679 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4682 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4683 int oldNbOfNodes=getNumberOfNodes();
4684 int nbOf1DCells=mesh1D->getNumberOfCells();
4686 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4687 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4688 int nbOfLevsInVec=nbOf1DCells+1;
4689 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4690 double *retPtr=ret->getPointer();
4691 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4692 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4693 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4694 tmp->setCoords(tmp2);
4695 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4696 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4697 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4698 for(int i=1;i<nbOfLevsInVec;i++)
4700 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4701 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4702 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4703 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4704 tmp->translate(vec);
4705 double tmp3[2],radius,alpha,alpha0;
4706 const double *p0=i+1<nbOfLevsInVec?begin:third;
4707 const double *p1=i+1<nbOfLevsInVec?end:begin;
4708 const double *p2=i+1<nbOfLevsInVec?third:end;
4709 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4710 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]);
4711 double angle=acos(cosangle/(radius*radius));
4712 tmp->rotate(end,0,angle);
4713 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4719 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4720 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4721 * \return newCoords new coords filled by this method.
4723 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4726 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4727 int oldNbOfNodes=getNumberOfNodes();
4728 int nbOf1DCells=mesh1D->getNumberOfCells();
4730 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4731 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4732 int nbOfLevsInVec=nbOf1DCells+1;
4733 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4734 double *retPtr=ret->getPointer();
4735 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4736 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4737 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4738 tmp->setCoords(tmp2);
4739 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4740 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4741 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4742 for(int i=1;i<nbOfLevsInVec;i++)
4744 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4745 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4746 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4747 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4748 tmp->translate(vec);
4749 double tmp3[2],radius,alpha,alpha0;
4750 const double *p0=i+1<nbOfLevsInVec?begin:third;
4751 const double *p1=i+1<nbOfLevsInVec?end:begin;
4752 const double *p2=i+1<nbOfLevsInVec?third:end;
4753 double vecPlane[3]={
4754 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4755 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4756 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4758 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4761 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4762 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4763 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4765 double c2=cos(asin(s2));
4767 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4768 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4769 {-vec2[1]*s2, vec2[0]*s2, c2}
4771 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]};
4772 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]};
4773 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]};
4774 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4775 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]);
4776 double angle=acos(cosangle/(radius*radius));
4777 tmp->rotate(end,vecPlane,angle);
4780 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4786 * This method is private because not easy to use for end user. This method is const contrary to
4787 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4788 * the coords sorted slice by slice.
4789 * \param isQuad specifies presence of quadratic cells.
4791 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4793 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4794 int nbOf2DCells=getNumberOfCells();
4795 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4796 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4797 const int *conn=_nodal_connec->getConstPointer();
4798 const int *connI=_nodal_connec_index->getConstPointer();
4799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4801 newConnI->alloc(nbOf3DCells+1,1);
4802 int *newConnIPtr=newConnI->getPointer();
4804 std::vector<int> newc;
4805 for(int j=0;j<nbOf2DCells;j++)
4807 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4808 *newConnIPtr++=(int)newc.size();
4810 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4811 int *newConnPtr=newConn->getPointer();
4812 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4813 newConnIPtr=newConnI->getPointer();
4814 for(int iz=0;iz<nbOf1DCells;iz++)
4817 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4818 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4820 int icell=(int)(iter-newc.begin());
4821 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4824 *newConnPtr=(*iter)+iz*deltaPerLev;
4829 *newConnPtr=(*iter);
4832 ret->setConnectivity(newConn,newConnI,true);
4833 ret->setCoords(getCoords());
4838 * Checks if \a this mesh is constituted by only quadratic cells.
4839 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4840 * \throw If the coordinates array is not set.
4841 * \throw If the nodal connectivity of cells is not defined.
4843 bool MEDCouplingUMesh::isFullyQuadratic() const
4845 checkFullyDefined();
4847 int nbOfCells=getNumberOfCells();
4848 for(int i=0;i<nbOfCells && ret;i++)
4850 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4851 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4852 ret=cm.isQuadratic();
4858 * Checks if \a this mesh includes any quadratic cell.
4859 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4860 * \throw If the coordinates array is not set.
4861 * \throw If the nodal connectivity of cells is not defined.
4863 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4865 checkFullyDefined();
4867 int nbOfCells=getNumberOfCells();
4868 for(int i=0;i<nbOfCells && !ret;i++)
4870 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4871 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4872 ret=cm.isQuadratic();
4878 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4879 * this mesh, it remains unchanged.
4880 * \throw If the coordinates array is not set.
4881 * \throw If the nodal connectivity of cells is not defined.
4883 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4885 checkFullyDefined();
4886 int nbOfCells=getNumberOfCells();
4888 const int *iciptr=_nodal_connec_index->getConstPointer();
4889 for(int i=0;i<nbOfCells;i++)
4891 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4892 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4893 if(cm.isQuadratic())
4895 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4896 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4897 if(!cml.isDynamic())
4898 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4900 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4907 const int *icptr=_nodal_connec->getConstPointer();
4908 newConn->alloc(getMeshLength()-delta,1);
4909 newConnI->alloc(nbOfCells+1,1);
4910 int *ocptr=newConn->getPointer();
4911 int *ociptr=newConnI->getPointer();
4914 for(int i=0;i<nbOfCells;i++,ociptr++)
4916 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4917 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4918 if(!cm.isQuadratic())
4920 _types.insert(type);
4921 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4922 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4926 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4927 _types.insert(typel);
4928 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4929 int newNbOfNodes=cml.getNumberOfNodes();
4931 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4932 *ocptr++=(int)typel;
4933 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4934 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4937 setConnectivity(newConn,newConnI,false);
4941 * This method converts all linear cell in \a this to quadratic one.
4942 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4943 * 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)
4944 * 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.
4945 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4946 * end of the existing coordinates.
4948 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4949 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4950 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4952 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4954 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4956 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4958 DataArrayInt *conn=0,*connI=0;
4959 DataArrayDouble *coords=0;
4960 std::set<INTERP_KERNEL::NormalizedCellType> types;
4961 checkFullyDefined();
4962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4963 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4964 int meshDim=getMeshDimension();
4965 switch(conversionType)
4971 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4972 connSafe=conn; connISafe=connI; coordsSafe=coords;
4975 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4976 connSafe=conn; connISafe=connI; coordsSafe=coords;
4979 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4980 connSafe=conn; connISafe=connI; coordsSafe=coords;
4983 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4991 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4992 connSafe=conn; connISafe=connI; coordsSafe=coords;
4995 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4996 connSafe=conn; connISafe=connI; coordsSafe=coords;
4999 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5000 connSafe=conn; connISafe=connI; coordsSafe=coords;
5003 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5008 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5010 setConnectivity(connSafe,connISafe,false);
5012 setCoords(coordsSafe);
5017 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5018 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5019 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5021 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5023 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5026 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5027 int nbOfCells=getNumberOfCells();
5028 int nbOfNodes=getNumberOfNodes();
5029 const int *cPtr=_nodal_connec->getConstPointer();
5030 const int *icPtr=_nodal_connec_index->getConstPointer();
5031 int lastVal=0,offset=nbOfNodes;
5032 for(int i=0;i<nbOfCells;i++,icPtr++)
5034 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5035 if(type==INTERP_KERNEL::NORM_SEG2)
5037 types.insert(INTERP_KERNEL::NORM_SEG3);
5038 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5039 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5040 newConn->pushBackSilent(offset++);
5042 newConnI->pushBackSilent(lastVal);
5043 ret->pushBackSilent(i);
5048 lastVal+=(icPtr[1]-icPtr[0]);
5049 newConnI->pushBackSilent(lastVal);
5050 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5053 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5054 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5058 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
5060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5062 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5064 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5065 DataArrayInt *conn1D=0,*conn1DI=0;
5066 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5067 DataArrayDouble *coordsTmp=0;
5068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5069 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5071 const int *c1DPtr=conn1D->begin();
5072 const int *c1DIPtr=conn1DI->begin();
5073 int nbOfCells=getNumberOfCells();
5074 const int *cPtr=_nodal_connec->getConstPointer();
5075 const int *icPtr=_nodal_connec_index->getConstPointer();
5077 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5079 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5080 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5081 if(!cm.isQuadratic())
5083 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5084 types.insert(typ2); newConn->pushBackSilent(typ2);
5085 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5086 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5087 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5088 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5089 newConnI->pushBackSilent(lastVal);
5090 ret->pushBackSilent(i);
5095 lastVal+=(icPtr[1]-icPtr[0]);
5096 newConnI->pushBackSilent(lastVal);
5097 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5100 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5105 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5106 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5107 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5109 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5113 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5114 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5117 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5120 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5126 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5127 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5128 DataArrayInt *conn1D=0,*conn1DI=0;
5129 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5130 DataArrayDouble *coordsTmp=0;
5131 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5132 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5134 const int *c1DPtr=conn1D->begin();
5135 const int *c1DIPtr=conn1DI->begin();
5136 int nbOfCells=getNumberOfCells();
5137 const int *cPtr=_nodal_connec->getConstPointer();
5138 const int *icPtr=_nodal_connec_index->getConstPointer();
5139 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5140 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5142 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5143 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5144 if(!cm.isQuadratic())
5146 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5147 types.insert(typ2); newConn->pushBackSilent(typ2);
5148 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5149 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5150 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5151 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5152 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5153 newConnI->pushBackSilent(lastVal);
5154 ret->pushBackSilent(i);
5159 lastVal+=(icPtr[1]-icPtr[0]);
5160 newConnI->pushBackSilent(lastVal);
5161 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5164 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5165 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5170 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5171 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5172 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5174 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5176 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5177 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5178 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5181 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5184 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5190 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5192 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5193 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5194 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5195 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5196 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5199 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5202 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5203 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5204 int nbOfCells=getNumberOfCells();
5205 const int *cPtr=_nodal_connec->getConstPointer();
5206 const int *icPtr=_nodal_connec_index->getConstPointer();
5207 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5208 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5210 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5211 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5212 if(!cm.isQuadratic())
5214 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5215 if(typ2==INTERP_KERNEL::NORM_ERROR)
5217 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5218 throw INTERP_KERNEL::Exception(oss.str().c_str());
5220 types.insert(typ2); newConn->pushBackSilent(typ2);
5221 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5222 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5223 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5224 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5226 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5227 int tmpPos=newConn->getNumberOfTuples();
5228 newConn->pushBackSilent(nodeId2);
5229 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5231 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5232 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5233 newConnI->pushBackSilent(lastVal);
5234 ret->pushBackSilent(i);
5239 lastVal+=(icPtr[1]-icPtr[0]);
5240 newConnI->pushBackSilent(lastVal);
5241 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5246 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5247 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5248 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5249 int *c=newConn->getPointer();
5250 const int *cI(newConnI->begin());
5251 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5252 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5253 offset=coordsTmp2Safe->getNumberOfTuples();
5254 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5255 c[cI[(*elt)+1]-1]+=offset;
5256 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5261 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5262 * so that the number of cells remains the same. Quadratic faces are converted to
5263 * polygons. This method works only for 2D meshes in
5264 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5265 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5266 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5267 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5268 * a polylinized edge constituting the input polygon.
5269 * \throw If the coordinates array is not set.
5270 * \throw If the nodal connectivity of cells is not defined.
5271 * \throw If \a this->getMeshDimension() != 2.
5272 * \throw If \a this->getSpaceDimension() != 2.
5274 void MEDCouplingUMesh::tessellate2D(double eps)
5276 checkFullyDefined();
5277 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5278 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5279 double epsa=fabs(eps);
5280 if(epsa<std::numeric_limits<double>::min())
5281 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 !");
5282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5286 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5287 revDesc1=0; revDescIndx1=0;
5288 mDesc->tessellate2DCurve(eps);
5289 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5290 setCoords(mDesc->getCoords());
5294 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5295 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5296 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5297 * a sub-divided edge.
5298 * \throw If the coordinates array is not set.
5299 * \throw If the nodal connectivity of cells is not defined.
5300 * \throw If \a this->getMeshDimension() != 1.
5301 * \throw If \a this->getSpaceDimension() != 2.
5303 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5305 checkFullyDefined();
5306 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5307 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5308 double epsa=fabs(eps);
5309 if(epsa<std::numeric_limits<double>::min())
5310 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 !");
5311 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5312 int nbCells=getNumberOfCells();
5313 int nbNodes=getNumberOfNodes();
5314 const int *conn=_nodal_connec->getConstPointer();
5315 const int *connI=_nodal_connec_index->getConstPointer();
5316 const double *coords=_coords->getConstPointer();
5317 std::vector<double> addCoo;
5318 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5320 newConnI->alloc(nbCells+1,1);
5321 int *newConnIPtr=newConnI->getPointer();
5324 INTERP_KERNEL::Node *tmp2[3];
5325 std::set<INTERP_KERNEL::NormalizedCellType> types;
5326 for(int i=0;i<nbCells;i++,newConnIPtr++)
5328 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5329 if(cm.isQuadratic())
5330 {//assert(connI[i+1]-connI[i]-1==3)
5331 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5332 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5333 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5334 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5335 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5338 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5339 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5341 newConnIPtr[1]=(int)newConn.size();
5345 types.insert(INTERP_KERNEL::NORM_SEG2);
5346 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5347 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5348 newConnIPtr[1]=newConnIPtr[0]+3;
5353 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5354 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5355 newConnIPtr[1]=newConnIPtr[0]+3;
5358 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5361 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5363 newConnArr->alloc((int)newConn.size(),1);
5364 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5365 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5366 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5367 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5368 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5369 std::copy(addCoo.begin(),addCoo.end(),work);
5370 DataArrayDouble::SetArrayIn(newCoords,_coords);
5375 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5376 * In addition, returns an array mapping new cells to old ones. <br>
5377 * This method typically increases the number of cells in \a this mesh
5378 * but the number of nodes remains \b unchanged.
5379 * That's why the 3D splitting policies
5380 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5381 * \param [in] policy - specifies a pattern used for splitting.
5382 * The semantic of \a policy is:
5383 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5384 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5385 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5386 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5387 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5388 * an id of old cell producing it. The caller is to delete this array using
5389 * decrRef() as it is no more needed.
5390 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5391 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5392 * and \a this->getMeshDimension() != 3.
5393 * \throw If \a policy is not one of the four discussed above.
5394 * \throw If the nodal connectivity of cells is not defined.
5395 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5397 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5402 return simplexizePol0();
5404 return simplexizePol1();
5405 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5406 return simplexizePlanarFace5();
5407 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5408 return simplexizePlanarFace6();
5410 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)");
5415 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5416 * - 1D: INTERP_KERNEL::NORM_SEG2
5417 * - 2D: INTERP_KERNEL::NORM_TRI3
5418 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5420 * This method is useful for users that need to use P1 field services as
5421 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5422 * All these methods need mesh support containing only simplex cells.
5423 * \return bool - \c true if there are only simplex cells in \a this mesh.
5424 * \throw If the coordinates array is not set.
5425 * \throw If the nodal connectivity of cells is not defined.
5426 * \throw If \a this->getMeshDimension() < 1.
5428 bool MEDCouplingUMesh::areOnlySimplexCells() const
5430 checkFullyDefined();
5431 int mdim=getMeshDimension();
5432 if(mdim<1 || mdim>3)
5433 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5434 int nbCells=getNumberOfCells();
5435 const int *conn=_nodal_connec->getConstPointer();
5436 const int *connI=_nodal_connec_index->getConstPointer();
5437 for(int i=0;i<nbCells;i++)
5439 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5447 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5449 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5451 checkConnectivityFullyDefined();
5452 if(getMeshDimension()!=2)
5453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5454 int nbOfCells=getNumberOfCells();
5455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5456 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5457 ret->alloc(nbOfCells+nbOfCutCells,1);
5458 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5459 int *retPt=ret->getPointer();
5460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5462 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5463 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5464 int *pt=newConn->getPointer();
5465 int *ptI=newConnI->getPointer();
5467 const int *oldc=_nodal_connec->getConstPointer();
5468 const int *ci=_nodal_connec_index->getConstPointer();
5469 for(int i=0;i<nbOfCells;i++,ci++)
5471 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5473 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5474 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5475 pt=std::copy(tmp,tmp+8,pt);
5484 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5485 ptI[1]=ptI[0]+ci[1]-ci[0];
5490 _nodal_connec->decrRef();
5491 _nodal_connec=newConn.retn();
5492 _nodal_connec_index->decrRef();
5493 _nodal_connec_index=newConnI.retn();
5500 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5502 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5504 checkConnectivityFullyDefined();
5505 if(getMeshDimension()!=2)
5506 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5507 int nbOfCells=getNumberOfCells();
5508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5509 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5510 ret->alloc(nbOfCells+nbOfCutCells,1);
5511 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5512 int *retPt=ret->getPointer();
5513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5515 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5516 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5517 int *pt=newConn->getPointer();
5518 int *ptI=newConnI->getPointer();
5520 const int *oldc=_nodal_connec->getConstPointer();
5521 const int *ci=_nodal_connec_index->getConstPointer();
5522 for(int i=0;i<nbOfCells;i++,ci++)
5524 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5526 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5527 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5528 pt=std::copy(tmp,tmp+8,pt);
5537 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5538 ptI[1]=ptI[0]+ci[1]-ci[0];
5543 _nodal_connec->decrRef();
5544 _nodal_connec=newConn.retn();
5545 _nodal_connec_index->decrRef();
5546 _nodal_connec_index=newConnI.retn();
5553 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5555 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5557 checkConnectivityFullyDefined();
5558 if(getMeshDimension()!=3)
5559 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5560 int nbOfCells=getNumberOfCells();
5561 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5562 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5563 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5564 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5565 int *retPt=ret->getPointer();
5566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5568 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5569 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5570 int *pt=newConn->getPointer();
5571 int *ptI=newConnI->getPointer();
5573 const int *oldc=_nodal_connec->getConstPointer();
5574 const int *ci=_nodal_connec_index->getConstPointer();
5575 for(int i=0;i<nbOfCells;i++,ci++)
5577 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5579 for(int j=0;j<5;j++,pt+=5,ptI++)
5581 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5582 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];
5589 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5590 ptI[1]=ptI[0]+ci[1]-ci[0];
5595 _nodal_connec->decrRef();
5596 _nodal_connec=newConn.retn();
5597 _nodal_connec_index->decrRef();
5598 _nodal_connec_index=newConnI.retn();
5605 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5607 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5609 checkConnectivityFullyDefined();
5610 if(getMeshDimension()!=3)
5611 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5612 int nbOfCells=getNumberOfCells();
5613 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5614 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5615 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5616 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5617 int *retPt=ret->getPointer();
5618 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5619 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5620 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5621 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5622 int *pt=newConn->getPointer();
5623 int *ptI=newConnI->getPointer();
5625 const int *oldc=_nodal_connec->getConstPointer();
5626 const int *ci=_nodal_connec_index->getConstPointer();
5627 for(int i=0;i<nbOfCells;i++,ci++)
5629 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5631 for(int j=0;j<6;j++,pt+=5,ptI++)
5633 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5634 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];
5641 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5642 ptI[1]=ptI[0]+ci[1]-ci[0];
5647 _nodal_connec->decrRef();
5648 _nodal_connec=newConn.retn();
5649 _nodal_connec_index->decrRef();
5650 _nodal_connec_index=newConnI.retn();
5657 * 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.
5658 * This method completly ignore coordinates.
5659 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5660 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5661 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5662 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5664 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5666 checkFullyDefined();
5667 if(getMeshDimension()!=2)
5668 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5669 int nbOfCells=getNumberOfCells();
5670 int *connI=_nodal_connec_index->getPointer();
5672 for(int i=0;i<nbOfCells;i++,connI++)
5674 int offset=descIndex[i];
5675 int nbOfEdges=descIndex[i+1]-offset;
5677 bool ddirect=desc[offset+nbOfEdges-1]>0;
5678 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5679 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5680 for(int j=0;j<nbOfEdges;j++)
5682 bool direct=desc[offset+j]>0;
5683 int edgeId=std::abs(desc[offset+j])-1;
5684 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5686 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5687 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5688 int ref2=direct?id1:id2;
5691 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5692 newConnLgth+=nbOfSubNodes-1;
5697 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5698 throw INTERP_KERNEL::Exception(oss.str().c_str());
5703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5706 newConnLgth++;//+1 is for cell type
5707 connI[1]=newConnLgth;
5710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5711 newConn->alloc(newConnLgth,1);
5712 int *work=newConn->getPointer();
5713 for(int i=0;i<nbOfCells;i++)
5715 *work++=INTERP_KERNEL::NORM_POLYGON;
5716 int offset=descIndex[i];
5717 int nbOfEdges=descIndex[i+1]-offset;
5718 for(int j=0;j<nbOfEdges;j++)
5720 bool direct=desc[offset+j]>0;
5721 int edgeId=std::abs(desc[offset+j])-1;
5723 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5726 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5727 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5728 work=std::copy(it,it+nbOfSubNodes-1,work);
5732 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5735 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5739 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5740 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5741 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5742 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5743 * so it can be useful to call mergeNodes() before calling this method.
5744 * \throw If \a this->getMeshDimension() <= 1.
5745 * \throw If the coordinates array is not set.
5746 * \throw If the nodal connectivity of cells is not defined.
5748 void MEDCouplingUMesh::convertDegeneratedCells()
5750 checkFullyDefined();
5751 if(getMeshDimension()<=1)
5752 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5753 int nbOfCells=getNumberOfCells();
5756 int initMeshLgth=getMeshLength();
5757 int *conn=_nodal_connec->getPointer();
5758 int *index=_nodal_connec_index->getPointer();
5762 for(int i=0;i<nbOfCells;i++)
5764 lgthOfCurCell=index[i+1]-posOfCurCell;
5765 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5767 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5768 conn+newPos+1,newLgth);
5769 conn[newPos]=newType;
5771 posOfCurCell=index[i+1];
5774 if(newPos!=initMeshLgth)
5775 _nodal_connec->reAlloc(newPos);
5780 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5781 * A cell is considered to be oriented correctly if an angle between its
5782 * normal vector and a given vector is less than \c PI / \c 2.
5783 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5785 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5787 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5788 * is not cleared before filling in.
5789 * \throw If \a this->getMeshDimension() != 2.
5790 * \throw If \a this->getSpaceDimension() != 3.
5792 * \if ENABLE_EXAMPLES
5793 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5794 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5797 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5799 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5800 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5801 int nbOfCells=getNumberOfCells();
5802 const int *conn=_nodal_connec->getConstPointer();
5803 const int *connI=_nodal_connec_index->getConstPointer();
5804 const double *coordsPtr=_coords->getConstPointer();
5805 for(int i=0;i<nbOfCells;i++)
5807 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5808 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5810 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5811 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5818 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5819 * considered to be oriented correctly if an angle between its normal vector and a
5820 * given vector is less than \c PI / \c 2.
5821 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5823 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5825 * \throw If \a this->getMeshDimension() != 2.
5826 * \throw If \a this->getSpaceDimension() != 3.
5828 * \if ENABLE_EXAMPLES
5829 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5830 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5833 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5835 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5836 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5837 int nbOfCells=getNumberOfCells();
5838 int *conn=_nodal_connec->getPointer();
5839 const int *connI=_nodal_connec_index->getConstPointer();
5840 const double *coordsPtr=_coords->getConstPointer();
5841 bool isModified=false;
5842 for(int i=0;i<nbOfCells;i++)
5844 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5845 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5847 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5848 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5853 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5854 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5855 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5859 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5860 std::vector<int> tmp0(sz-1),tmp1(sz);
5861 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5862 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5863 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5864 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5870 _nodal_connec->declareAsNew();
5875 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5876 * oriented facets. The normal vector of the facet should point out of the cell.
5877 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5878 * is not cleared before filling in.
5879 * \throw If \a this->getMeshDimension() != 3.
5880 * \throw If \a this->getSpaceDimension() != 3.
5881 * \throw If the coordinates array is not set.
5882 * \throw If the nodal connectivity of cells is not defined.
5884 * \if ENABLE_EXAMPLES
5885 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5886 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5889 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5891 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5892 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5893 int nbOfCells=getNumberOfCells();
5894 const int *conn=_nodal_connec->getConstPointer();
5895 const int *connI=_nodal_connec_index->getConstPointer();
5896 const double *coordsPtr=_coords->getConstPointer();
5897 for(int i=0;i<nbOfCells;i++)
5899 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5900 if(type==INTERP_KERNEL::NORM_POLYHED)
5902 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5909 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5911 * \throw If \a this->getMeshDimension() != 3.
5912 * \throw If \a this->getSpaceDimension() != 3.
5913 * \throw If the coordinates array is not set.
5914 * \throw If the nodal connectivity of cells is not defined.
5915 * \throw If the reparation fails.
5917 * \if ENABLE_EXAMPLES
5918 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5919 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5921 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5923 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5925 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5926 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5927 int nbOfCells=getNumberOfCells();
5928 int *conn=_nodal_connec->getPointer();
5929 const int *connI=_nodal_connec_index->getConstPointer();
5930 const double *coordsPtr=_coords->getConstPointer();
5931 for(int i=0;i<nbOfCells;i++)
5933 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5934 if(type==INTERP_KERNEL::NORM_POLYHED)
5938 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5939 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5941 catch(INTERP_KERNEL::Exception& e)
5943 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5944 throw INTERP_KERNEL::Exception(oss.str().c_str());
5952 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5953 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5954 * according to which the first facet of the cell should be oriented to have the normal vector
5955 * pointing out of cell.
5956 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5957 * cells. The caller is to delete this array using decrRef() as it is no more
5959 * \throw If \a this->getMeshDimension() != 3.
5960 * \throw If \a this->getSpaceDimension() != 3.
5961 * \throw If the coordinates array is not set.
5962 * \throw If the nodal connectivity of cells is not defined.
5964 * \if ENABLE_EXAMPLES
5965 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5966 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5968 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5970 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5972 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5973 if(getMeshDimension()!=3)
5974 throw INTERP_KERNEL::Exception(msg);
5975 int spaceDim=getSpaceDimension();
5977 throw INTERP_KERNEL::Exception(msg);
5979 int nbOfCells=getNumberOfCells();
5980 int *conn=_nodal_connec->getPointer();
5981 const int *connI=_nodal_connec_index->getConstPointer();
5982 const double *coo=getCoords()->getConstPointer();
5983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5984 for(int i=0;i<nbOfCells;i++)
5986 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5987 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5989 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5991 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5992 cells->pushBackSilent(i);
5996 return cells.retn();
6000 * This method is a faster method to correct orientation of all 3D cells in \a this.
6001 * 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.
6002 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6004 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6005 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6007 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6009 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6010 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6011 int nbOfCells=getNumberOfCells();
6012 int *conn=_nodal_connec->getPointer();
6013 const int *connI=_nodal_connec_index->getConstPointer();
6014 const double *coordsPtr=_coords->getConstPointer();
6015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6016 for(int i=0;i<nbOfCells;i++)
6018 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6021 case INTERP_KERNEL::NORM_TETRA4:
6023 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6025 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6026 ret->pushBackSilent(i);
6030 case INTERP_KERNEL::NORM_PYRA5:
6032 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6034 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6035 ret->pushBackSilent(i);
6039 case INTERP_KERNEL::NORM_PENTA6:
6040 case INTERP_KERNEL::NORM_HEXA8:
6041 case INTERP_KERNEL::NORM_HEXGP12:
6043 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6045 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6046 ret->pushBackSilent(i);
6050 case INTERP_KERNEL::NORM_POLYHED:
6052 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6054 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6055 ret->pushBackSilent(i);
6060 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 !");
6068 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6069 * If it is not the case an exception will be thrown.
6070 * This method is fast because the first cell of \a this is used to compute the plane.
6071 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6072 * \param pos output of size at least 3 used to store a point owned of searched plane.
6074 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6076 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6077 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6078 const int *conn=_nodal_connec->getConstPointer();
6079 const int *connI=_nodal_connec_index->getConstPointer();
6080 const double *coordsPtr=_coords->getConstPointer();
6081 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6082 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6086 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6087 * cells. Currently cells of the following types are treated:
6088 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6089 * For a cell of other type an exception is thrown.
6090 * Space dimension of a 2D mesh can be either 2 or 3.
6091 * The Edge Ratio of a cell \f$t\f$ is:
6092 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6093 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6094 * the smallest edge lengths of \f$t\f$.
6095 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6096 * cells and one time, lying on \a this mesh. The caller is to delete this
6097 * field using decrRef() as it is no more needed.
6098 * \throw If the coordinates array is not set.
6099 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6100 * \throw If the connectivity data array has more than one component.
6101 * \throw If the connectivity data array has a named component.
6102 * \throw If the connectivity index data array has more than one component.
6103 * \throw If the connectivity index data array has a named component.
6104 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6105 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6106 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6108 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6111 int spaceDim=getSpaceDimension();
6112 int meshDim=getMeshDimension();
6113 if(spaceDim!=2 && spaceDim!=3)
6114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6115 if(meshDim!=2 && meshDim!=3)
6116 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6117 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6119 int nbOfCells=getNumberOfCells();
6120 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6121 arr->alloc(nbOfCells,1);
6122 double *pt=arr->getPointer();
6123 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6124 const int *conn=_nodal_connec->getConstPointer();
6125 const int *connI=_nodal_connec_index->getConstPointer();
6126 const double *coo=_coords->getConstPointer();
6128 for(int i=0;i<nbOfCells;i++,pt++)
6130 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6133 case INTERP_KERNEL::NORM_TRI3:
6135 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6136 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6139 case INTERP_KERNEL::NORM_QUAD4:
6141 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6142 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6145 case INTERP_KERNEL::NORM_TETRA4:
6147 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6148 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6152 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6154 conn+=connI[i+1]-connI[i];
6156 ret->setName("EdgeRatio");
6157 ret->synchronizeTimeWithSupport();
6162 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6163 * cells. Currently cells of the following types are treated:
6164 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6165 * For a cell of other type an exception is thrown.
6166 * Space dimension of a 2D mesh can be either 2 or 3.
6167 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6168 * cells and one time, lying on \a this mesh. The caller is to delete this
6169 * field using decrRef() as it is no more needed.
6170 * \throw If the coordinates array is not set.
6171 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6172 * \throw If the connectivity data array has more than one component.
6173 * \throw If the connectivity data array has a named component.
6174 * \throw If the connectivity index data array has more than one component.
6175 * \throw If the connectivity index data array has a named component.
6176 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6177 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6178 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6180 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6183 int spaceDim=getSpaceDimension();
6184 int meshDim=getMeshDimension();
6185 if(spaceDim!=2 && spaceDim!=3)
6186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6187 if(meshDim!=2 && meshDim!=3)
6188 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6189 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6191 int nbOfCells=getNumberOfCells();
6192 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6193 arr->alloc(nbOfCells,1);
6194 double *pt=arr->getPointer();
6195 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6196 const int *conn=_nodal_connec->getConstPointer();
6197 const int *connI=_nodal_connec_index->getConstPointer();
6198 const double *coo=_coords->getConstPointer();
6200 for(int i=0;i<nbOfCells;i++,pt++)
6202 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6205 case INTERP_KERNEL::NORM_TRI3:
6207 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6208 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6211 case INTERP_KERNEL::NORM_QUAD4:
6213 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6214 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6217 case INTERP_KERNEL::NORM_TETRA4:
6219 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6220 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6224 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6226 conn+=connI[i+1]-connI[i];
6228 ret->setName("AspectRatio");
6229 ret->synchronizeTimeWithSupport();
6234 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6235 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6236 * treated: INTERP_KERNEL::NORM_QUAD4.
6237 * For a cell of other type an exception is thrown.
6238 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6239 * cells and one time, lying on \a this mesh. The caller is to delete this
6240 * field using decrRef() as it is no more needed.
6241 * \throw If the coordinates array is not set.
6242 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6243 * \throw If the connectivity data array has more than one component.
6244 * \throw If the connectivity data array has a named component.
6245 * \throw If the connectivity index data array has more than one component.
6246 * \throw If the connectivity index data array has a named component.
6247 * \throw If \a this->getMeshDimension() != 2.
6248 * \throw If \a this->getSpaceDimension() != 3.
6249 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6251 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6254 int spaceDim=getSpaceDimension();
6255 int meshDim=getMeshDimension();
6257 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6259 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6260 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6262 int nbOfCells=getNumberOfCells();
6263 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6264 arr->alloc(nbOfCells,1);
6265 double *pt=arr->getPointer();
6266 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6267 const int *conn=_nodal_connec->getConstPointer();
6268 const int *connI=_nodal_connec_index->getConstPointer();
6269 const double *coo=_coords->getConstPointer();
6271 for(int i=0;i<nbOfCells;i++,pt++)
6273 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6276 case INTERP_KERNEL::NORM_QUAD4:
6278 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6279 *pt=INTERP_KERNEL::quadWarp(tmp);
6283 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6285 conn+=connI[i+1]-connI[i];
6287 ret->setName("Warp");
6288 ret->synchronizeTimeWithSupport();
6294 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6295 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6296 * treated: INTERP_KERNEL::NORM_QUAD4.
6297 * For a cell of other type an exception is thrown.
6298 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6299 * cells and one time, lying on \a this mesh. The caller is to delete this
6300 * field using decrRef() as it is no more needed.
6301 * \throw If the coordinates array is not set.
6302 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6303 * \throw If the connectivity data array has more than one component.
6304 * \throw If the connectivity data array has a named component.
6305 * \throw If the connectivity index data array has more than one component.
6306 * \throw If the connectivity index data array has a named component.
6307 * \throw If \a this->getMeshDimension() != 2.
6308 * \throw If \a this->getSpaceDimension() != 3.
6309 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6311 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6314 int spaceDim=getSpaceDimension();
6315 int meshDim=getMeshDimension();
6317 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6320 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6322 int nbOfCells=getNumberOfCells();
6323 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6324 arr->alloc(nbOfCells,1);
6325 double *pt=arr->getPointer();
6326 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6327 const int *conn=_nodal_connec->getConstPointer();
6328 const int *connI=_nodal_connec_index->getConstPointer();
6329 const double *coo=_coords->getConstPointer();
6331 for(int i=0;i<nbOfCells;i++,pt++)
6333 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6336 case INTERP_KERNEL::NORM_QUAD4:
6338 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6339 *pt=INTERP_KERNEL::quadSkew(tmp);
6343 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6345 conn+=connI[i+1]-connI[i];
6347 ret->setName("Skew");
6348 ret->synchronizeTimeWithSupport();
6353 * This method aggregate the bbox of each cell and put it into bbox parameter.
6355 * \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)
6356 * For all other cases this input parameter is ignored.
6357 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6359 * \throw If \a this is not fully set (coordinates and connectivity).
6360 * \throw If a cell in \a this has no valid nodeId.
6361 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6363 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6365 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6366 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.
6367 return getBoundingBoxForBBTreeFast();
6368 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6370 bool presenceOfQuadratic(false);
6371 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6373 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6374 if(cm.isQuadratic())
6375 presenceOfQuadratic=true;
6377 if(!presenceOfQuadratic)
6378 return getBoundingBoxForBBTreeFast();
6379 if(mDim==2 && sDim==2)
6380 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6382 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6384 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) !");
6388 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6389 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6391 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6393 * \throw If \a this is not fully set (coordinates and connectivity).
6394 * \throw If a cell in \a this has no valid nodeId.
6396 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6398 checkFullyDefined();
6399 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6400 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6401 double *bbox(ret->getPointer());
6402 for(int i=0;i<nbOfCells*spaceDim;i++)
6404 bbox[2*i]=std::numeric_limits<double>::max();
6405 bbox[2*i+1]=-std::numeric_limits<double>::max();
6407 const double *coordsPtr(_coords->getConstPointer());
6408 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6409 for(int i=0;i<nbOfCells;i++)
6411 int offset=connI[i]+1;
6412 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6413 for(int j=0;j<nbOfNodesForCell;j++)
6415 int nodeId=conn[offset+j];
6416 if(nodeId>=0 && nodeId<nbOfNodes)
6418 for(int k=0;k<spaceDim;k++)
6420 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6421 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6428 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6429 throw INTERP_KERNEL::Exception(oss.str().c_str());
6436 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6437 * useful for 2D meshes having quadratic cells
6438 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6439 * the two extremities of the arc of circle).
6441 * \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)
6442 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6443 * \throw If \a this is not fully defined.
6444 * \throw If \a this is not a mesh with meshDimension equal to 2.
6445 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6446 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6448 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6450 checkFullyDefined();
6451 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6452 if(spaceDim!=2 || mDim!=2)
6453 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!");
6454 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6455 double *bbox(ret->getPointer());
6456 const double *coords(_coords->getConstPointer());
6457 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6458 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6460 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6461 int sz(connI[1]-connI[0]-1);
6462 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6463 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6464 INTERP_KERNEL::QuadraticPolygon *pol(0);
6465 for(int j=0;j<sz;j++)
6467 int nodeId(conn[*connI+1+j]);
6468 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6470 if(!cm.isQuadratic())
6471 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6473 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6474 INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6475 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6481 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6482 * useful for 2D meshes having quadratic cells
6483 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6484 * the two extremities of the arc of circle).
6486 * \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)
6487 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6488 * \throw If \a this is not fully defined.
6489 * \throw If \a this is not a mesh with meshDimension equal to 1.
6490 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6491 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6493 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6495 checkFullyDefined();
6496 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6497 if(spaceDim!=2 || mDim!=1)
6498 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!");
6499 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6500 double *bbox(ret->getPointer());
6501 const double *coords(_coords->getConstPointer());
6502 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6503 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6505 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6506 int sz(connI[1]-connI[0]-1);
6507 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6508 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6509 INTERP_KERNEL::Edge *edge(0);
6510 for(int j=0;j<sz;j++)
6512 int nodeId(conn[*connI+1+j]);
6513 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6515 if(!cm.isQuadratic())
6516 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6518 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6519 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6520 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6527 namespace ParaMEDMEMImpl
6532 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6533 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6542 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6543 bool operator() (const int& pos) { return _conn[pos]==_val; }
6553 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6554 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6555 * \a this is composed in cell types.
6556 * The returned array is of size 3*n where n is the number of different types present in \a this.
6557 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6558 * This parameter is kept only for compatibility with other methode listed above.
6560 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6562 checkConnectivityFullyDefined();
6563 const int *conn=_nodal_connec->getConstPointer();
6564 const int *connI=_nodal_connec_index->getConstPointer();
6565 const int *work=connI;
6566 int nbOfCells=getNumberOfCells();
6567 std::size_t n=getAllGeoTypes().size();
6568 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6569 std::set<INTERP_KERNEL::NormalizedCellType> types;
6570 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6572 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6573 if(types.find(typ)!=types.end())
6575 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6576 oss << " is not contiguous !";
6577 throw INTERP_KERNEL::Exception(oss.str().c_str());
6581 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6582 ret[3*i+1]=(int)std::distance(work,work2);
6589 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6590 * only for types cell, type node is not managed.
6591 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6592 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6593 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6594 * If 2 or more same geometric type is in \a code and exception is thrown too.
6596 * This method firstly checks
6597 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6598 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6599 * an exception is thrown too.
6601 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6602 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6603 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6605 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6608 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6609 std::size_t sz=code.size();
6612 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6613 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6615 bool isNoPflUsed=true;
6616 for(std::size_t i=0;i<n;i++)
6617 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6619 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6621 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6622 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6623 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6626 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6629 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6631 if(types.size()==_types.size())
6634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6636 int *retPtr=ret->getPointer();
6637 const int *connI=_nodal_connec_index->getConstPointer();
6638 const int *conn=_nodal_connec->getConstPointer();
6639 int nbOfCells=getNumberOfCells();
6642 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6644 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6645 int offset=(int)std::distance(connI,i);
6646 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6647 int nbOfCellsOfCurType=(int)std::distance(i,j);
6648 if(code[3*kk+2]==-1)
6649 for(int k=0;k<nbOfCellsOfCurType;k++)
6653 int idInIdsPerType=code[3*kk+2];
6654 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6656 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6659 zePfl->checkAllocated();
6660 if(zePfl->getNumberOfComponents()==1)
6662 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6664 if(*k>=0 && *k<nbOfCellsOfCurType)
6665 *retPtr=(*k)+offset;
6668 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6669 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6670 throw INTERP_KERNEL::Exception(oss.str().c_str());
6675 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6682 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6683 oss << " should be in [0," << idsPerType.size() << ") !";
6684 throw INTERP_KERNEL::Exception(oss.str().c_str());
6693 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6694 * 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.
6695 * 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.
6696 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6698 * \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.
6699 * \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,
6700 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6701 * \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.
6702 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6703 * \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
6705 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6709 if(profile->getNumberOfComponents()!=1)
6710 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6711 checkConnectivityFullyDefined();
6712 const int *conn=_nodal_connec->getConstPointer();
6713 const int *connI=_nodal_connec_index->getConstPointer();
6714 int nbOfCells=getNumberOfCells();
6715 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6716 std::vector<int> typeRangeVals(1);
6717 for(const int *i=connI;i!=connI+nbOfCells;)
6719 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6720 if(std::find(types.begin(),types.end(),curType)!=types.end())
6722 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6724 types.push_back(curType);
6725 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6726 typeRangeVals.push_back((int)std::distance(connI,i));
6729 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6730 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6731 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6732 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6735 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6736 code.resize(3*nbOfCastsFinal);
6737 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6738 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6739 for(int i=0;i<nbOfCastsFinal;i++)
6741 int castId=castsPresent->getIJ(i,0);
6742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6743 idsInPflPerType2.push_back(tmp3);
6744 code[3*i]=(int)types[castId];
6745 code[3*i+1]=tmp3->getNumberOfTuples();
6746 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6747 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6749 tmp4->copyStringInfoFrom(*profile);
6750 idsPerType2.push_back(tmp4);
6751 code[3*i+2]=(int)idsPerType2.size()-1;
6758 std::size_t sz2=idsInPflPerType2.size();
6759 idsInPflPerType.resize(sz2);
6760 for(std::size_t i=0;i<sz2;i++)
6762 DataArrayInt *locDa=idsInPflPerType2[i];
6764 idsInPflPerType[i]=locDa;
6766 std::size_t sz=idsPerType2.size();
6767 idsPerType.resize(sz);
6768 for(std::size_t i=0;i<sz;i++)
6770 DataArrayInt *locDa=idsPerType2[i];
6772 idsPerType[i]=locDa;
6777 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6778 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6779 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6780 * 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.
6782 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6784 checkFullyDefined();
6785 nM1LevMesh->checkFullyDefined();
6786 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6787 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6788 if(_coords!=nM1LevMesh->getCoords())
6789 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6791 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6792 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6794 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6795 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6796 tmp->setConnectivity(tmp0,tmp1);
6797 tmp->renumberCells(ret0->getConstPointer(),false);
6798 revDesc=tmp->getNodalConnectivity();
6799 revDescIndx=tmp->getNodalConnectivityIndex();
6800 DataArrayInt *ret=0;
6801 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6804 ret->getMaxValue(tmp2);
6806 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6807 throw INTERP_KERNEL::Exception(oss.str().c_str());
6812 revDescIndx->incrRef();
6815 meshnM1Old2New=ret0;
6820 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6821 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6822 * in "Old to New" mode.
6823 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6824 * this array using decrRef() as it is no more needed.
6825 * \throw If the nodal connectivity of cells is not defined.
6827 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6829 checkConnectivityFullyDefined();
6830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6831 renumberCells(ret->getConstPointer(),false);
6836 * This methods checks that cells are sorted by their types.
6837 * This method makes asumption (no check) that connectivity is correctly set before calling.
6839 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6841 checkFullyDefined();
6842 const int *conn=_nodal_connec->getConstPointer();
6843 const int *connI=_nodal_connec_index->getConstPointer();
6844 int nbOfCells=getNumberOfCells();
6845 std::set<INTERP_KERNEL::NormalizedCellType> types;
6846 for(const int *i=connI;i!=connI+nbOfCells;)
6848 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6849 if(types.find(curType)!=types.end())
6851 types.insert(curType);
6852 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6858 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6859 * The geometric type order is specified by MED file.
6861 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6863 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6865 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6869 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6870 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6871 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6872 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6874 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6876 checkFullyDefined();
6877 const int *conn=_nodal_connec->getConstPointer();
6878 const int *connI=_nodal_connec_index->getConstPointer();
6879 int nbOfCells=getNumberOfCells();
6883 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6884 for(const int *i=connI;i!=connI+nbOfCells;)
6886 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6887 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6888 if(isTypeExists!=orderEnd)
6890 int pos=(int)std::distance(orderBg,isTypeExists);
6894 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6898 if(sg.find(curType)==sg.end())
6900 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6911 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6912 * 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
6913 * 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'.
6915 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6917 checkConnectivityFullyDefined();
6918 int nbOfCells=getNumberOfCells();
6919 const int *conn=_nodal_connec->getConstPointer();
6920 const int *connI=_nodal_connec_index->getConstPointer();
6921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6923 tmpa->alloc(nbOfCells,1);
6924 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6925 tmpb->fillWithZero();
6926 int *tmp=tmpa->getPointer();
6927 int *tmp2=tmpb->getPointer();
6928 for(const int *i=connI;i!=connI+nbOfCells;i++)
6930 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6933 int pos=(int)std::distance(orderBg,where);
6935 tmp[std::distance(connI,i)]=pos;
6939 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6940 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6941 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6942 throw INTERP_KERNEL::Exception(oss.str().c_str());
6945 nbPerType=tmpb.retn();
6950 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6952 * \return a new object containing the old to new correspondance.
6954 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6956 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6958 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6962 * 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.
6963 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6964 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6965 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6967 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6969 DataArrayInt *nbPerType=0;
6970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6971 nbPerType->decrRef();
6972 return tmpa->buildPermArrPerLevel();
6976 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6977 * The number of cells remains unchanged after the call of this method.
6978 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6979 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6981 * \return the array giving the correspondance old to new.
6983 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6985 checkFullyDefined();
6987 const int *conn=_nodal_connec->getConstPointer();
6988 const int *connI=_nodal_connec_index->getConstPointer();
6989 int nbOfCells=getNumberOfCells();
6990 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6991 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6992 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6994 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6995 types.push_back(curType);
6996 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6998 DataArrayInt *ret=DataArrayInt::New();
6999 ret->alloc(nbOfCells,1);
7000 int *retPtr=ret->getPointer();
7001 std::fill(retPtr,retPtr+nbOfCells,-1);
7003 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7005 for(const int *i=connI;i!=connI+nbOfCells;i++)
7006 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7007 retPtr[std::distance(connI,i)]=newCellId++;
7009 renumberCells(retPtr,false);
7014 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7015 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7016 * This method makes asumption that connectivity is correctly set before calling.
7018 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7020 checkConnectivityFullyDefined();
7021 const int *conn=_nodal_connec->getConstPointer();
7022 const int *connI=_nodal_connec_index->getConstPointer();
7023 int nbOfCells=getNumberOfCells();
7024 std::vector<MEDCouplingUMesh *> ret;
7025 for(const int *i=connI;i!=connI+nbOfCells;)
7027 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7028 int beginCellId=(int)std::distance(connI,i);
7029 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7030 int endCellId=(int)std::distance(connI,i);
7031 int sz=endCellId-beginCellId;
7032 int *cells=new int[sz];
7033 for(int j=0;j<sz;j++)
7034 cells[j]=beginCellId+j;
7035 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7043 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7044 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7045 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7047 * \return a newly allocated instance, that the caller must manage.
7048 * \throw If \a this contains more than one geometric type.
7049 * \throw If the nodal connectivity of \a this is not fully defined.
7050 * \throw If the internal data is not coherent.
7052 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7054 checkConnectivityFullyDefined();
7055 if(_types.size()!=1)
7056 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7057 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7058 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7059 ret->setCoords(getCoords());
7060 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7064 retC->setNodalConnectivity(c);
7068 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7070 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7071 DataArrayInt *c=0,*ci=0;
7072 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7073 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7074 retD->setNodalConnectivity(cs,cis);
7079 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7081 checkConnectivityFullyDefined();
7082 if(_types.size()!=1)
7083 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7084 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7085 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7088 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7089 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7090 throw INTERP_KERNEL::Exception(oss.str().c_str());
7092 int nbCells=getNumberOfCells();
7094 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7096 int *outPtr=connOut->getPointer();
7097 const int *conn=_nodal_connec->begin();
7098 const int *connI=_nodal_connec_index->begin();
7100 for(int i=0;i<nbCells;i++,connI++)
7102 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7103 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7106 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 << ") !";
7107 throw INTERP_KERNEL::Exception(oss.str().c_str());
7110 return connOut.retn();
7113 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7115 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7116 checkConnectivityFullyDefined();
7117 if(_types.size()!=1)
7118 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7119 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7121 throw INTERP_KERNEL::Exception(msg0);
7122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7123 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7124 int *cp(c->getPointer()),*cip(ci->getPointer());
7125 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7127 for(int i=0;i<nbCells;i++,cip++,incip++)
7129 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7130 int delta(stop-strt);
7133 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7134 cp=std::copy(incp+strt,incp+stop,cp);
7136 throw INTERP_KERNEL::Exception(msg0);
7139 throw INTERP_KERNEL::Exception(msg0);
7140 cip[1]=cip[0]+delta;
7142 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7146 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7147 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7148 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7149 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7150 * are not used here to avoid the build of big permutation array.
7152 * \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
7153 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7154 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7155 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7156 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7157 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7158 * \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
7159 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7161 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7162 DataArrayInt *&szOfCellGrpOfSameType,
7163 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7165 std::vector<const MEDCouplingUMesh *> ms2;
7166 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7169 (*it)->checkConnectivityFullyDefined();
7173 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7174 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7175 int meshDim=ms2[0]->getMeshDimension();
7176 std::vector<const MEDCouplingUMesh *> m1ssm;
7177 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7179 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7180 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7183 ret1->alloc(0,1); ret2->alloc(0,1);
7184 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7186 if(meshDim!=(*it)->getMeshDimension())
7187 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7188 if(refCoo!=(*it)->getCoords())
7189 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7190 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7191 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7192 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7193 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7195 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7196 m1ssmSingleAuto.push_back(singleCell);
7197 m1ssmSingle.push_back(singleCell);
7198 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7201 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7202 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7203 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7204 for(std::size_t i=0;i<m1ssm.size();i++)
7205 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7206 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7207 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7208 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7213 * This method returns a newly created DataArrayInt instance.
7214 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7216 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7218 checkFullyDefined();
7219 const int *conn=_nodal_connec->getConstPointer();
7220 const int *connIndex=_nodal_connec_index->getConstPointer();
7221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7222 for(const int *w=begin;w!=end;w++)
7223 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7224 ret->pushBackSilent(*w);
7229 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7230 * are in [0:getNumberOfCells())
7232 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7234 checkFullyDefined();
7235 const int *conn=_nodal_connec->getConstPointer();
7236 const int *connI=_nodal_connec_index->getConstPointer();
7237 int nbOfCells=getNumberOfCells();
7238 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7239 int *tmp=new int[nbOfCells];
7240 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7243 for(const int *i=connI;i!=connI+nbOfCells;i++)
7244 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7245 tmp[std::distance(connI,i)]=j++;
7247 DataArrayInt *ret=DataArrayInt::New();
7248 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7249 ret->copyStringInfoFrom(*da);
7250 int *retPtr=ret->getPointer();
7251 const int *daPtr=da->getConstPointer();
7252 int nbOfElems=da->getNbOfElems();
7253 for(int k=0;k<nbOfElems;k++)
7254 retPtr[k]=tmp[daPtr[k]];
7260 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7261 * This method \b works \b for mesh sorted by type.
7262 * cells whose ids is in 'idsPerGeoType' array.
7263 * This method conserves coords and name of mesh.
7265 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7267 std::vector<int> code=getDistributionOfTypes();
7268 std::size_t nOfTypesInThis=code.size()/3;
7269 int sz=0,szOfType=0;
7270 for(std::size_t i=0;i<nOfTypesInThis;i++)
7275 szOfType=code[3*i+1];
7277 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7278 if(*work<0 || *work>=szOfType)
7280 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7281 oss << ". It should be in [0," << szOfType << ") !";
7282 throw INTERP_KERNEL::Exception(oss.str().c_str());
7284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7285 int *idsPtr=idsTokeep->getPointer();
7287 for(std::size_t i=0;i<nOfTypesInThis;i++)
7290 for(int j=0;j<code[3*i+1];j++)
7293 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7294 offset+=code[3*i+1];
7296 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7297 ret->copyTinyInfoFrom(this);
7302 * This method returns a vector of size 'this->getNumberOfCells()'.
7303 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7305 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7307 int ncell=getNumberOfCells();
7308 std::vector<bool> ret(ncell);
7309 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7310 const int *c=getNodalConnectivity()->getConstPointer();
7311 for(int i=0;i<ncell;i++)
7313 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7314 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7315 ret[i]=cm.isQuadratic();
7321 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7323 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7325 if(other->getType()!=UNSTRUCTURED)
7326 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7327 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7328 return MergeUMeshes(this,otherC);
7332 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7333 * computed by averaging coordinates of cell nodes, so this method is not a right
7334 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7335 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7336 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7337 * components. The caller is to delete this array using decrRef() as it is
7339 * \throw If the coordinates array is not set.
7340 * \throw If the nodal connectivity of cells is not defined.
7341 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7343 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7345 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7346 int spaceDim=getSpaceDimension();
7347 int nbOfCells=getNumberOfCells();
7348 ret->alloc(nbOfCells,spaceDim);
7349 ret->copyStringInfoFrom(*getCoords());
7350 double *ptToFill=ret->getPointer();
7351 const int *nodal=_nodal_connec->getConstPointer();
7352 const int *nodalI=_nodal_connec_index->getConstPointer();
7353 const double *coor=_coords->getConstPointer();
7354 for(int i=0;i<nbOfCells;i++)
7356 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7357 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7364 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7365 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7367 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7368 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7370 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7371 * \throw If \a this is not fully defined (coordinates and connectivity)
7372 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7374 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7376 checkFullyDefined();
7377 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7378 int spaceDim=getSpaceDimension();
7379 int nbOfCells=getNumberOfCells();
7380 int nbOfNodes=getNumberOfNodes();
7381 ret->alloc(nbOfCells,spaceDim);
7382 double *ptToFill=ret->getPointer();
7383 const int *nodal=_nodal_connec->getConstPointer();
7384 const int *nodalI=_nodal_connec_index->getConstPointer();
7385 const double *coor=_coords->getConstPointer();
7386 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7388 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7389 std::fill(ptToFill,ptToFill+spaceDim,0.);
7390 if(type!=INTERP_KERNEL::NORM_POLYHED)
7392 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7394 if(*conn>=0 && *conn<nbOfNodes)
7395 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7398 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7399 throw INTERP_KERNEL::Exception(oss.str().c_str());
7402 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7403 if(nbOfNodesInCell>0)
7404 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7407 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7408 throw INTERP_KERNEL::Exception(oss.str().c_str());
7413 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7415 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7417 if(*it>=0 && *it<nbOfNodes)
7418 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7421 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7422 throw INTERP_KERNEL::Exception(oss.str().c_str());
7426 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7429 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7430 throw INTERP_KERNEL::Exception(oss.str().c_str());
7438 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7439 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7440 * are specified via an array of cell ids.
7441 * \warning Validity of the specified cell ids is not checked!
7442 * Valid range is [ 0, \a this->getNumberOfCells() ).
7443 * \param [in] begin - an array of cell ids of interest.
7444 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7445 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7446 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7447 * caller is to delete this array using decrRef() as it is no more needed.
7448 * \throw If the coordinates array is not set.
7449 * \throw If the nodal connectivity of cells is not defined.
7451 * \if ENABLE_EXAMPLES
7452 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7453 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7456 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7458 DataArrayDouble *ret=DataArrayDouble::New();
7459 int spaceDim=getSpaceDimension();
7460 int nbOfTuple=(int)std::distance(begin,end);
7461 ret->alloc(nbOfTuple,spaceDim);
7462 double *ptToFill=ret->getPointer();
7463 double *tmp=new double[spaceDim];
7464 const int *nodal=_nodal_connec->getConstPointer();
7465 const int *nodalI=_nodal_connec_index->getConstPointer();
7466 const double *coor=_coords->getConstPointer();
7467 for(const int *w=begin;w!=end;w++)
7469 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7470 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7478 * 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".
7479 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7480 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7481 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7482 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7484 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7485 * \throw If spaceDim!=3 or meshDim!=2.
7486 * \throw If connectivity of \a this is invalid.
7487 * \throw If connectivity of a cell in \a this points to an invalid node.
7489 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7491 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7492 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7493 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7494 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7495 ret->alloc(nbOfCells,4);
7496 double *retPtr(ret->getPointer());
7497 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7498 const double *coor(_coords->begin());
7499 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7501 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7502 if(nodalI[1]-nodalI[0]>=3)
7504 for(int j=0;j<3;j++)
7506 int nodeId(nodal[nodalI[0]+1+j]);
7507 if(nodeId>=0 && nodeId<nbOfNodes)
7508 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7511 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7512 throw INTERP_KERNEL::Exception(oss.str().c_str());
7518 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7519 throw INTERP_KERNEL::Exception(oss.str().c_str());
7521 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7522 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7528 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7531 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7534 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7535 da->checkAllocated();
7536 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7538 int nbOfTuples=da->getNumberOfTuples();
7539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7541 c->alloc(2*nbOfTuples,1);
7542 cI->alloc(nbOfTuples+1,1);
7543 int *cp=c->getPointer();
7544 int *cip=cI->getPointer();
7546 for(int i=0;i<nbOfTuples;i++)
7548 *cp++=INTERP_KERNEL::NORM_POINT1;
7552 ret->setConnectivity(c,cI,true);
7556 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7557 * Cells and nodes of
7558 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7559 * \param [in] mesh1 - the first mesh.
7560 * \param [in] mesh2 - the second mesh.
7561 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7562 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7563 * is no more needed.
7564 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7565 * \throw If the coordinates array is not set in none of the meshes.
7566 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7567 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7569 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7571 std::vector<const MEDCouplingUMesh *> tmp(2);
7572 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7573 return MergeUMeshes(tmp);
7577 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7578 * Cells and nodes of
7579 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7580 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7581 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7582 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7583 * is no more needed.
7584 * \throw If \a a.size() == 0.
7585 * \throw If \a a[ *i* ] == NULL.
7586 * \throw If the coordinates array is not set in none of the meshes.
7587 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7588 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7590 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7592 std::size_t sz=a.size();
7594 return MergeUMeshesLL(a);
7595 for(std::size_t ii=0;ii<sz;ii++)
7598 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7599 throw INTERP_KERNEL::Exception(oss.str().c_str());
7601 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7602 std::vector< const MEDCouplingUMesh * > aa(sz);
7604 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7606 const MEDCouplingUMesh *cur=a[i];
7607 const DataArrayDouble *coo=cur->getCoords();
7609 spaceDim=coo->getNumberOfComponents();
7612 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7613 for(std::size_t i=0;i<sz;i++)
7615 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7618 return MergeUMeshesLL(aa);
7623 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7626 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7627 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7628 int meshDim=(*it)->getMeshDimension();
7629 int nbOfCells=(*it)->getNumberOfCells();
7630 int meshLgth=(*it++)->getMeshLength();
7631 for(;it!=a.end();it++)
7633 if(meshDim!=(*it)->getMeshDimension())
7634 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7635 nbOfCells+=(*it)->getNumberOfCells();
7636 meshLgth+=(*it)->getMeshLength();
7638 std::vector<const MEDCouplingPointSet *> aps(a.size());
7639 std::copy(a.begin(),a.end(),aps.begin());
7640 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7641 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7642 ret->setCoords(pts);
7643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7644 c->alloc(meshLgth,1);
7645 int *cPtr=c->getPointer();
7646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7647 cI->alloc(nbOfCells+1,1);
7648 int *cIPtr=cI->getPointer();
7652 for(it=a.begin();it!=a.end();it++)
7654 int curNbOfCell=(*it)->getNumberOfCells();
7655 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7656 const int *curC=(*it)->_nodal_connec->getConstPointer();
7657 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7658 for(int j=0;j<curNbOfCell;j++)
7660 const int *src=curC+curCI[j];
7662 for(;src!=curC+curCI[j+1];src++,cPtr++)
7670 offset+=curCI[curNbOfCell];
7671 offset2+=(*it)->getNumberOfNodes();
7674 ret->setConnectivity(c,cI,true);
7681 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7682 * dimension and sharing the node coordinates array.
7683 * All cells of the first mesh precede all cells of the second mesh
7684 * within the result mesh.
7685 * \param [in] mesh1 - the first mesh.
7686 * \param [in] mesh2 - the second mesh.
7687 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7688 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7689 * is no more needed.
7690 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7691 * \throw If the meshes do not share the node coordinates array.
7692 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7693 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7695 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7697 std::vector<const MEDCouplingUMesh *> tmp(2);
7698 tmp[0]=mesh1; tmp[1]=mesh2;
7699 return MergeUMeshesOnSameCoords(tmp);
7703 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7704 * dimension and sharing the node coordinates array.
7705 * All cells of the *i*-th mesh precede all cells of the
7706 * (*i*+1)-th mesh within the result mesh.
7707 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7708 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7709 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7710 * is no more needed.
7711 * \throw If \a a.size() == 0.
7712 * \throw If \a a[ *i* ] == NULL.
7713 * \throw If the meshes do not share the node coordinates array.
7714 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7715 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7717 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7720 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7721 for(std::size_t ii=0;ii<meshes.size();ii++)
7724 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7725 throw INTERP_KERNEL::Exception(oss.str().c_str());
7727 const DataArrayDouble *coords=meshes.front()->getCoords();
7728 int meshDim=meshes.front()->getMeshDimension();
7729 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7731 int meshIndexLgth=0;
7732 for(;iter!=meshes.end();iter++)
7734 if(coords!=(*iter)->getCoords())
7735 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7736 if(meshDim!=(*iter)->getMeshDimension())
7737 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7738 meshLgth+=(*iter)->getMeshLength();
7739 meshIndexLgth+=(*iter)->getNumberOfCells();
7741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7742 nodal->alloc(meshLgth,1);
7743 int *nodalPtr=nodal->getPointer();
7744 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7745 nodalIndex->alloc(meshIndexLgth+1,1);
7746 int *nodalIndexPtr=nodalIndex->getPointer();
7748 for(iter=meshes.begin();iter!=meshes.end();iter++)
7750 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7751 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7752 int nbOfCells=(*iter)->getNumberOfCells();
7753 int meshLgth2=(*iter)->getMeshLength();
7754 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7755 if(iter!=meshes.begin())
7756 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7758 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7761 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7762 ret->setName("merge");
7763 ret->setMeshDimension(meshDim);
7764 ret->setConnectivity(nodal,nodalIndex,true);
7765 ret->setCoords(coords);
7770 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7771 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7772 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7773 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7774 * New" mode are returned for each input mesh.
7775 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7776 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7777 * valid values [0,1,2], see zipConnectivityTraducer().
7778 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7779 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7780 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7782 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7783 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7784 * is no more needed.
7785 * \throw If \a meshes.size() == 0.
7786 * \throw If \a meshes[ *i* ] == NULL.
7787 * \throw If the meshes do not share the node coordinates array.
7788 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7789 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7790 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7791 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7793 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7795 //All checks are delegated to MergeUMeshesOnSameCoords
7796 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7798 corr.resize(meshes.size());
7799 std::size_t nbOfMeshes=meshes.size();
7801 const int *o2nPtr=o2n->getConstPointer();
7802 for(std::size_t i=0;i<nbOfMeshes;i++)
7804 DataArrayInt *tmp=DataArrayInt::New();
7805 int curNbOfCells=meshes[i]->getNumberOfCells();
7806 tmp->alloc(curNbOfCells,1);
7807 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7808 offset+=curNbOfCells;
7809 tmp->setName(meshes[i]->getName());
7816 * Makes all given meshes share the nodal connectivity array. The common connectivity
7817 * array is created by concatenating the connectivity arrays of all given meshes. All
7818 * the given meshes must be of the same space dimension but dimension of cells **can
7819 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7820 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7821 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7822 * \param [in,out] meshes - a vector of meshes to update.
7823 * \throw If any of \a meshes is NULL.
7824 * \throw If the coordinates array is not set in any of \a meshes.
7825 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7826 * \throw If \a meshes are of different space dimension.
7828 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7830 std::size_t sz=meshes.size();
7833 std::vector< const DataArrayDouble * > coords(meshes.size());
7834 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7835 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7839 (*it)->checkConnectivityFullyDefined();
7840 const DataArrayDouble *coo=(*it)->getCoords();
7845 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7846 oss << " has no coordinate array defined !";
7847 throw INTERP_KERNEL::Exception(oss.str().c_str());
7852 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7853 oss << " is null !";
7854 throw INTERP_KERNEL::Exception(oss.str().c_str());
7857 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7858 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7859 int offset=(*it)->getNumberOfNodes();
7860 (*it++)->setCoords(res);
7861 for(;it!=meshes.end();it++)
7863 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7864 (*it)->setCoords(res);
7865 (*it)->shiftNodeNumbersInConn(offset);
7866 offset+=oldNumberOfNodes;
7871 * Merges nodes coincident with a given precision within all given meshes that share
7872 * the nodal connectivity array. The given meshes **can be of different** mesh
7873 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7874 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7875 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7876 * \param [in,out] meshes - a vector of meshes to update.
7877 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7878 * \throw If any of \a meshes is NULL.
7879 * \throw If the \a meshes do not share the same node coordinates array.
7880 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7882 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7886 std::set<const DataArrayDouble *> s;
7887 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7890 s.insert((*it)->getCoords());
7893 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 !";
7894 throw INTERP_KERNEL::Exception(oss.str().c_str());
7899 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 !";
7900 throw INTERP_KERNEL::Exception(oss.str().c_str());
7902 const DataArrayDouble *coo=*(s.begin());
7906 DataArrayInt *comm,*commI;
7907 coo->findCommonTuples(eps,-1,comm,commI);
7908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7909 int oldNbOfNodes=coo->getNumberOfTuples();
7911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7912 if(oldNbOfNodes==newNbOfNodes)
7914 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7915 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7917 (*it)->renumberNodesInConn(o2n->getConstPointer());
7918 (*it)->setCoords(newCoords);
7923 * 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.
7924 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7925 * \param isQuad specifies the policy of connectivity.
7926 * @ret in/out parameter in which the result will be append
7928 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7930 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7931 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7932 ret.push_back(cm.getExtrudedType());
7933 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7936 case INTERP_KERNEL::NORM_POINT1:
7938 ret.push_back(connBg[1]);
7939 ret.push_back(connBg[1]+nbOfNodesPerLev);
7942 case INTERP_KERNEL::NORM_SEG2:
7944 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7945 ret.insert(ret.end(),conn,conn+4);
7948 case INTERP_KERNEL::NORM_SEG3:
7950 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7951 ret.insert(ret.end(),conn,conn+8);
7954 case INTERP_KERNEL::NORM_QUAD4:
7956 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7957 ret.insert(ret.end(),conn,conn+8);
7960 case INTERP_KERNEL::NORM_TRI3:
7962 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7963 ret.insert(ret.end(),conn,conn+6);
7966 case INTERP_KERNEL::NORM_TRI6:
7968 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,
7969 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7970 ret.insert(ret.end(),conn,conn+15);
7973 case INTERP_KERNEL::NORM_QUAD8:
7976 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7977 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7978 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7980 ret.insert(ret.end(),conn,conn+20);
7983 case INTERP_KERNEL::NORM_POLYGON:
7985 std::back_insert_iterator< std::vector<int> > ii(ret);
7986 std::copy(connBg+1,connEnd,ii);
7988 std::reverse_iterator<const int *> rConnBg(connEnd);
7989 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7990 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7991 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7992 for(std::size_t i=0;i<nbOfRadFaces;i++)
7995 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7996 std::copy(conn,conn+4,ii);
8001 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8006 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8008 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8011 double v[3]={0.,0.,0.};
8012 std::size_t sz=std::distance(begin,end);
8017 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];
8018 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8019 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8021 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8023 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8024 // SEG3 forming a circle):
8025 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8027 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8028 for(std::size_t j=0;j<sz;j++)
8030 if (j%2) // current point i is quadratic, next point i+1 is standard
8033 ip1 = (j+1)%sz; // ip1 = "i+1"
8035 else // current point i is standard, next point i+1 is quadratic
8040 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8041 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8042 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8044 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8050 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8052 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8054 std::vector<std::pair<int,int> > edges;
8055 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8056 const int *bgFace=begin;
8057 for(std::size_t i=0;i<nbOfFaces;i++)
8059 const int *endFace=std::find(bgFace+1,end,-1);
8060 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8061 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8063 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8064 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8066 edges.push_back(p1);
8070 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8074 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8076 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8078 double vec0[3],vec1[3];
8079 std::size_t sz=std::distance(begin,end);
8081 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8082 int nbOfNodes=(int)sz/2;
8083 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8084 const double *pt0=coords+3*begin[0];
8085 const double *pt1=coords+3*begin[nbOfNodes];
8086 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8087 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8090 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8092 std::size_t sz=std::distance(begin,end);
8093 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8094 std::size_t nbOfNodes(sz/2);
8095 std::copy(begin,end,(int *)tmp);
8096 for(std::size_t j=1;j<nbOfNodes;j++)
8098 begin[j]=tmp[nbOfNodes-j];
8099 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8103 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8105 std::size_t sz=std::distance(begin,end);
8107 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8108 double vec0[3],vec1[3];
8109 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8110 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];
8111 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;
8114 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8116 std::size_t sz=std::distance(begin,end);
8118 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8120 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8121 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8122 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8126 * 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 )
8127 * 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
8130 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8131 * \param [in] coords the coordinates with nb of components exactly equal to 3
8132 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8133 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8134 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8136 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8138 int nbFaces=std::count(begin+1,end,-1)+1;
8139 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8140 double *vPtr=v->getPointer();
8141 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8142 double *pPtr=p->getPointer();
8143 const int *stFaceConn=begin+1;
8144 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8146 const int *endFaceConn=std::find(stFaceConn,end,-1);
8147 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8148 stFaceConn=endFaceConn+1;
8150 pPtr=p->getPointer(); vPtr=v->getPointer();
8151 DataArrayInt *comm1=0,*commI1=0;
8152 v->findCommonTuples(eps,-1,comm1,commI1);
8153 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8154 const int *comm1Ptr=comm1->getConstPointer();
8155 const int *commI1Ptr=commI1->getConstPointer();
8156 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8157 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8159 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8160 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8161 mm->finishInsertingCells();
8163 for(int i=0;i<nbOfGrps1;i++)
8165 int vecId=comm1Ptr[commI1Ptr[i]];
8166 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8167 DataArrayInt *comm2=0,*commI2=0;
8168 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8170 const int *comm2Ptr=comm2->getConstPointer();
8171 const int *commI2Ptr=commI2->getConstPointer();
8172 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8173 for(int j=0;j<nbOfGrps2;j++)
8175 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8177 res->insertAtTheEnd(begin,end);
8178 res->pushBackSilent(-1);
8182 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8184 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8185 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8187 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8190 const int *idsNodePtr=idsNode->getConstPointer();
8191 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];
8192 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8193 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8194 if(std::abs(norm)>eps)
8196 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8197 mm3->rotate(center,vec,angle);
8199 mm3->changeSpaceDimension(2);
8200 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8201 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8202 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8203 int nbOfCells=mm4->getNumberOfCells();
8204 for(int k=0;k<nbOfCells;k++)
8207 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8208 res->pushBackSilent(idsNodePtr[*work]);
8209 res->pushBackSilent(-1);
8214 res->popBackSilent();
8218 * 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
8219 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8221 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8222 * \param [in] coords coordinates expected to have 3 components.
8223 * \param [in] begin start of the nodal connectivity of the face.
8224 * \param [in] end end of the nodal connectivity (excluded) of the face.
8225 * \param [out] v the normalized vector of size 3
8226 * \param [out] p the pos of plane
8228 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8230 std::size_t nbPoints=std::distance(begin,end);
8232 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8233 double vec[3]={0.,0.,0.};
8235 bool refFound=false;
8236 for(;j<nbPoints-1 && !refFound;j++)
8238 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8239 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8240 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8241 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8245 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8248 for(std::size_t i=j;i<nbPoints-1;i++)
8251 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8252 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8253 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8254 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8257 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8258 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];
8259 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8262 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8263 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8267 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8271 * This method tries to obtain a well oriented polyhedron.
8272 * If the algorithm fails, an exception will be thrown.
8274 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8276 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8277 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8278 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8280 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8281 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8282 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8284 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8287 std::size_t smthChanged=0;
8288 for(std::size_t i=0;i<nbOfFaces;i++)
8290 endFace=std::find(bgFace+1,end,-1);
8291 nbOfEdgesInFace=std::distance(bgFace,endFace);
8295 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8297 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8298 std::pair<int,int> p2(p1.second,p1.first);
8299 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8300 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8301 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8306 std::reverse(bgFace+1,endFace);
8307 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8309 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8310 std::pair<int,int> p2(p1.second,p1.first);
8311 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8312 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8313 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8314 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8315 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8316 if(it!=edgesOK.end())
8319 edgesFinished.push_back(p1);
8322 edgesOK.push_back(p1);
8329 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8331 if(!edgesOK.empty())
8332 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8333 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8334 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8336 for(std::size_t i=0;i<nbOfFaces;i++)
8338 endFace=std::find(bgFace+1,end,-1);
8339 std::reverse(bgFace+1,endFace);
8345 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8347 int nbOfNodesExpected(skin->getNumberOfNodes());
8348 const int *n2oPtr(n2o->getConstPointer());
8349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8350 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8351 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8352 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8353 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8355 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8356 if(nbOfNodesExpected<1)
8358 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8359 *work++=n2oPtr[prevNode];
8360 for(int i=1;i<nbOfNodesExpected;i++)
8362 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8364 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8365 conn.erase(prevNode);
8368 int curNode(*(conn.begin()));
8369 *work++=n2oPtr[curNode];
8370 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8371 shar.erase(prevCell);
8374 prevCell=*(shar.begin());
8378 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8384 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8389 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8391 int nbOfNodesExpected(skin->getNumberOfNodes());
8392 int nbOfTurn(nbOfNodesExpected/2);
8393 const int *n2oPtr(n2o->getConstPointer());
8394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8395 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8396 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8397 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8398 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8400 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8401 if(nbOfNodesExpected<1)
8403 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8404 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8405 for(int i=1;i<nbOfTurn;i++)
8407 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8409 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8410 conn.erase(prevNode);
8413 int curNode(*(conn.begin()));
8414 *work=n2oPtr[curNode];
8415 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8416 shar.erase(prevCell);
8419 int curCell(*(shar.begin()));
8420 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8429 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8432 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8438 * This method makes the assumption spacedimension == meshdimension == 2.
8439 * This method works only for linear cells.
8441 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8443 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8445 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8447 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8448 int oldNbOfNodes(skin->getNumberOfNodes());
8449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8450 int nbOfNodesExpected(skin->getNumberOfNodes());
8451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8452 int nbCells(skin->getNumberOfCells());
8453 if(nbCells==nbOfNodesExpected)
8454 return buildUnionOf2DMeshLinear(skin,n2o);
8455 else if(2*nbCells==nbOfNodesExpected)
8456 return buildUnionOf2DMeshQuadratic(skin,n2o);
8458 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8462 * This method makes the assumption spacedimension == meshdimension == 3.
8463 * This method works only for linear cells.
8465 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8467 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8469 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8470 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8471 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8472 const int *conn=m->getNodalConnectivity()->getConstPointer();
8473 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8474 int nbOfCells=m->getNumberOfCells();
8475 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8476 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8479 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8480 for(int i=1;i<nbOfCells;i++)
8483 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8489 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8490 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8492 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8496 for(int i=0;i<nbOfNodesInCell;i++)
8497 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8498 else if(spaceDim==2)
8500 for(int i=0;i<nbOfNodesInCell;i++)
8502 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8507 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8510 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8512 int nbOfCells=getNumberOfCells();
8514 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8515 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};
8516 ofs << " <" << getVTKDataSetType() << ">\n";
8517 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8518 ofs << " <PointData>\n" << pointData << std::endl;
8519 ofs << " </PointData>\n";
8520 ofs << " <CellData>\n" << cellData << std::endl;
8521 ofs << " </CellData>\n";
8522 ofs << " <Points>\n";
8523 if(getSpaceDimension()==3)
8524 _coords->writeVTK(ofs,8,"Points",byteData);
8527 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8528 coo->writeVTK(ofs,8,"Points",byteData);
8530 ofs << " </Points>\n";
8531 ofs << " <Cells>\n";
8532 const int *cPtr=_nodal_connec->getConstPointer();
8533 const int *cIPtr=_nodal_connec_index->getConstPointer();
8534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8535 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8536 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8538 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8539 int szFaceOffsets=0,szConn=0;
8540 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8543 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8546 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8547 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8551 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8552 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8553 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8554 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8555 w4=std::copy(c.begin(),c.end(),w4);
8558 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8559 types->writeVTK(ofs,8,"UInt8","types",byteData);
8560 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8561 if(szFaceOffsets!=0)
8562 {//presence of Polyhedra
8563 connectivity->reAlloc(szConn);
8564 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8565 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8566 w1=faces->getPointer();
8567 for(int i=0;i<nbOfCells;i++)
8568 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8570 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8572 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8573 for(int j=0;j<nbFaces;j++)
8575 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8576 *w1++=(int)std::distance(w6,w5);
8577 w1=std::copy(w6,w5,w1);
8581 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8583 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8584 ofs << " </Cells>\n";
8585 ofs << " </Piece>\n";
8586 ofs << " </" << getVTKDataSetType() << ">\n";
8589 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8591 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8593 { stream << " Not set !"; return ; }
8594 stream << " Mesh dimension : " << _mesh_dim << ".";
8598 { stream << " No coordinates set !"; return ; }
8599 if(!_coords->isAllocated())
8600 { stream << " Coordinates set but not allocated !"; return ; }
8601 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8602 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8603 if(!_nodal_connec_index)
8604 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8605 if(!_nodal_connec_index->isAllocated())
8606 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8607 int lgth=_nodal_connec_index->getNumberOfTuples();
8608 int cpt=_nodal_connec_index->getNumberOfComponents();
8609 if(cpt!=1 || lgth<1)
8611 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8614 std::string MEDCouplingUMesh::getVTKDataSetType() const
8616 return std::string("UnstructuredGrid");
8620 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8621 * returns a result mesh constituted by polygons.
8622 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8623 * all nodes from m2.
8624 * The meshes should be in 2D space. In
8625 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8627 * \param [in] m1 - the first input mesh which is a partitioned object.
8628 * \param [in] m2 - the second input mesh which is a partition tool.
8629 * \param [in] eps - precision used to detect coincident mesh entities.
8630 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8631 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8632 * this array using decrRef() as it is no more needed.
8633 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8634 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8635 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8636 * any cell of \a m2. The caller is to delete this array using decrRef() as
8637 * it is no more needed.
8638 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8639 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8640 * is no more needed.
8641 * \throw If the coordinates array is not set in any of the meshes.
8642 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8643 * \throw If any of the meshes is not a 2D mesh in 2D space.
8645 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8646 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8648 m1->checkFullyDefined();
8649 m2->checkFullyDefined();
8650 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8653 // Step 1: compute all edge intersections (new nodes)
8654 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8655 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8656 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8657 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8658 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8659 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8660 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8661 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8662 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8663 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8664 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8665 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8667 // Step 2: re-order newly created nodes according to the ordering found in m2
8668 std::vector< std::vector<int> > intersectEdge2;
8669 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8670 subDiv2.clear(); dd5=0; dd6=0;
8673 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8674 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8675 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8676 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8678 // Step 4: Prepare final result:
8679 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8680 addCooDa->alloc((int)(addCoo.size())/2,2);
8681 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8682 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8683 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8684 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8685 std::vector<const DataArrayDouble *> coordss(4);
8686 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8687 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8688 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8691 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8692 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8693 ret->setConnectivity(conn,connI,true);
8694 ret->setCoords(coo);
8695 cellNb1=c1.retn(); cellNb2=c2.retn();
8701 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8702 * (newly created) nodes corresponding to the edge intersections.
8704 * @param[out] cr, crI connectivity of the resulting mesh
8705 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8706 * TODO: describe input parameters
8708 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8709 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8710 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8711 const std::vector<double>& addCoords,
8712 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8714 static const int SPACEDIM=2;
8715 const double *coo1=m1->getCoords()->getConstPointer();
8716 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8717 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8718 int offset1=m1->getNumberOfNodes();
8719 const double *coo2=m2->getCoords()->getConstPointer();
8720 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8721 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8722 int offset2=offset1+m2->getNumberOfNodes();
8723 int offset3=offset2+((int)addCoords.size())/2;
8724 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8725 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8726 // Here a BBTree on 2D-cells, not on segments:
8727 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8728 int ncell1=m1->getNumberOfCells();
8730 for(int i=0;i<ncell1;i++)
8732 std::vector<int> candidates2;
8733 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8734 std::map<INTERP_KERNEL::Node *,int> mapp;
8735 std::map<int,INTERP_KERNEL::Node *> mappRev;
8736 INTERP_KERNEL::QuadraticPolygon pol1;
8737 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8738 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8739 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8740 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8741 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8742 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8743 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8745 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
8746 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8747 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8748 for(it1.first();!it1.finished();it1.next())
8749 edges1.insert(it1.current()->getPtr());
8751 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8752 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8754 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8756 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8757 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8758 // Complete mapping with elements coming from the current cell it2 in mesh2:
8759 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8760 // pol2 is the new QP in the final merged result.
8761 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8762 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8765 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8767 pol1.initLocationsWithOther(pol2s[ii]);
8768 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8769 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8770 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8772 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8773 // by m2 but that we still want to keep in the final result.
8778 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8780 catch(INTERP_KERNEL::Exception& e)
8782 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();
8783 throw INTERP_KERNEL::Exception(oss.str().c_str());
8786 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8787 (*it).second->decrRef();
8791 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8793 std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8795 throw INTERP_KERNEL::Exception("Internal error in remapping !");
8796 int v((*it).second);
8797 if(v==forbVal0 || v==forbVal1)
8799 if(std::find(isect.begin(),isect.end(),v)==isect.end())
8803 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8808 bool presenceOfOn(false);
8809 for(int i=0;i<sz;i++)
8811 INTERP_KERNEL::ElementaryEdge *e(c[i]);
8812 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8814 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8815 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8817 return presenceOfOn;
8821 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
8822 * To do the work this method can optionnaly needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
8823 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
8824 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8826 * \return int - the number of new nodes created (in most of cases 0).
8828 * \throw If \a this is not coherent.
8829 * \throw If \a this has not spaceDim equal to 2.
8830 * \throw If \a this has not meshDim equal to 2.
8831 * \throw If some subcells needed to be split are orphan.
8832 * \sa MEDCouplingUMesh::conformize2D
8834 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8836 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8838 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8839 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8840 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8841 if(midOpt==0 && midOptI==0)
8843 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8846 else if(midOpt!=0 && midOptI!=0)
8847 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8853 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8854 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8855 * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
8856 * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
8857 * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
8859 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
8860 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
8862 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
8863 * This method expects that all nodes in \a this are not closer than \a eps.
8864 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
8866 * \param [in] eps the relative error to detect merged edges.
8867 * \return DataArrayInt * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
8868 * that the user is expected to deal with.
8870 * \throw If \a this is not coherent.
8871 * \throw If \a this has not spaceDim equal to 2.
8872 * \throw If \a this has not meshDim equal to 2.
8873 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
8875 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
8877 static const int SPACEDIM=2;
8879 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
8882 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
8883 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
8884 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
8885 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
8886 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
8887 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
8888 std::vector<double> addCoo;
8889 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
8890 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8891 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8892 for(int i=0;i<nDescCell;i++)
8894 std::vector<int> candidates;
8895 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
8896 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8899 std::map<INTERP_KERNEL::Node *,int> m;
8900 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
8901 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
8902 INTERP_KERNEL::MergePoints merge;
8903 INTERP_KERNEL::QuadraticPolygon c1,c2;
8904 e1->intersectWith(e2,merge,c1,c2);
8905 e1->decrRef(); e2->decrRef();
8906 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
8907 overlapEdge[i].push_back(*it);
8908 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
8909 overlapEdge[*it].push_back(i);
8910 for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8911 (*it2).first->decrRef();
8914 // splitting done. sort intersect point in intersectEdge.
8915 std::vector< std::vector<int> > middle(nDescCell);
8916 int nbOf2DCellsToBeSplit(0);
8917 bool middleNeedsToBeUsed(false);
8918 std::vector<bool> cells2DToTreat(nDescCell,false);
8919 for(int i=0;i<nDescCell;i++)
8921 std::vector<int>& isect(intersectEdge[i]);
8922 int sz((int)isect.size());
8925 std::map<INTERP_KERNEL::Node *,int> m;
8926 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
8927 e->sortSubNodesAbs(coords,isect);
8929 for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8930 (*it2).first->decrRef();
8934 int idx0(rdi[i]),idx1(rdi[i+1]);
8936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
8937 if(!cells2DToTreat[rd[idx0]])
8939 cells2DToTreat[rd[idx0]]=true;
8940 nbOf2DCellsToBeSplit++;
8942 // try to reuse at most eventual 'middle' of SEG3
8943 std::vector<int>& mid(middle[i]);
8944 mid.resize(sz+1,-1);
8945 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
8947 middleNeedsToBeUsed=true;
8948 const std::vector<int>& candidates(overlapEdge[i]);
8949 std::vector<int> trueCandidates;
8950 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
8951 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
8952 trueCandidates.push_back(*itc);
8953 int stNode(c[ci[i]+1]),endNode(isect[0]);
8954 for(int j=0;j<sz+1;j++)
8956 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
8958 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
8959 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
8960 { mid[j]=*itc; break; }
8963 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
8968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
8969 if(nbOf2DCellsToBeSplit==0)
8972 int *retPtr(ret->getPointer());
8973 for(int i=0;i<nCell;i++)
8974 if(cells2DToTreat[i])
8977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
8978 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
8979 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
8980 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
8981 if(middleNeedsToBeUsed)
8982 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
8983 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
8984 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
8985 setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
8986 setPartOfMySelf(ret->begin(),ret->end(),*modif);
8988 bool areNodesMerged; int newNbOfNodes;
8989 if(nbOfNodesCreated!=0)
8990 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
8996 * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
8997 * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
8998 * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
8999 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9000 * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
9001 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9003 * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
9004 * using new instance, idem for coordinates.
9006 * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
9008 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
9010 * \throw If \a this is not coherent.
9011 * \throw If \a this has not spaceDim equal to 2.
9012 * \throw If \a this has not meshDim equal to 2.
9014 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9016 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9020 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9021 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9022 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9023 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9024 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9025 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9026 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9027 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9028 const double *coords(_coords->begin());
9029 int *newciptr(newci->getPointer());
9030 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9032 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9033 ret->pushBackSilent(i);
9034 newciptr[1]=newc->getNumberOfTuples();
9039 if(!appendedCoords->empty())
9041 appendedCoords->rearrange(2);
9042 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9044 setCoords(newCoords);
9047 setConnectivity(newc,newci,true);
9052 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9053 * It builds the descending connectivity of the two meshes, and then using a binary tree
9054 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9055 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9057 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9058 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9059 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9060 std::vector<double>& addCoo,
9061 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9062 throw(INTERP_KERNEL::Exception)
9064 static const int SPACEDIM=2;
9065 // Build desc connectivity
9066 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9067 desc2=DataArrayInt::New();
9068 descIndx2=DataArrayInt::New();
9069 revDesc2=DataArrayInt::New();
9070 revDescIndx2=DataArrayInt::New();
9071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9073 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9074 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9075 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9076 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
9077 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
9079 // Build BB tree of all edges in the tool mesh (second mesh)
9080 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9081 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9082 int nDescCell1=m1Desc->getNumberOfCells();
9083 int nDescCell2=m2Desc->getNumberOfCells();
9084 intersectEdge1.resize(nDescCell1);
9085 colinear2.resize(nDescCell2);
9086 subDiv2.resize(nDescCell2);
9087 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9089 std::vector<int> candidates1(1);
9090 int offset1=m1->getNumberOfNodes();
9091 int offset2=offset1+m2->getNumberOfNodes();
9092 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
9094 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9095 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9096 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9098 std::map<INTERP_KERNEL::Node *,int> map1,map2;
9099 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9100 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9102 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9103 // 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
9104 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9105 std::set<INTERP_KERNEL::Node *> nodes;
9106 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9107 std::size_t szz(nodes.size());
9108 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9109 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9110 for(std::size_t iii=0;iii<szz;iii++,itt++)
9111 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9112 // end of protection
9113 // Performs egde cutting:
9114 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9119 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9121 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9122 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9126 * This method performs the 2nd step of Partition of 2D mesh.
9127 * This method has 4 inputs :
9128 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9129 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9130 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9131 * 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'
9132 * Nodes end up lying consecutively on a cutted edge.
9133 * \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.
9134 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9135 * \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.
9136 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9137 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9139 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9140 const std::vector<double>& addCoo,
9141 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9143 int offset1=m1->getNumberOfNodes();
9144 int ncell=m2->getNumberOfCells();
9145 const int *c=m2->getNodalConnectivity()->getConstPointer();
9146 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9147 const double *coo=m2->getCoords()->getConstPointer();
9148 const double *cooBis=m1->getCoords()->getConstPointer();
9149 int offset2=offset1+m2->getNumberOfNodes();
9150 intersectEdge.resize(ncell);
9151 for(int i=0;i<ncell;i++,cI++)
9153 const std::vector<int>& divs=subDiv[i];
9154 int nnode=cI[1]-cI[0]-1;
9155 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9156 std::map<INTERP_KERNEL::Node *, int> mapp22;
9157 for(int j=0;j<nnode;j++)
9159 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9160 int nnid=c[(*cI)+j+1];
9161 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9162 mapp22[nn]=nnid+offset1;
9164 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9165 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9166 ((*it).second.first)->decrRef();
9167 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9168 std::map<INTERP_KERNEL::Node *,int> mapp3;
9169 for(std::size_t j=0;j<divs.size();j++)
9172 INTERP_KERNEL::Node *tmp=0;
9174 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9176 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9178 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9182 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9183 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9190 * 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).
9191 * 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
9192 * with a plane. The result will be put in 'cut3DSuf' out parameter.
9193 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9194 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9195 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9196 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9197 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9198 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9199 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9200 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9201 * \param [out] cut3DSuf input/output param.
9203 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9204 const int *nodal3DCurve, const int *nodalIndx3DCurve,
9205 const int *desc, const int *descIndx,
9206 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
9208 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9209 int nbOf3DSurfCell=(int)cut3DSurf.size();
9210 for(int i=0;i<nbOf3DSurfCell;i++)
9212 std::vector<int> res;
9213 int offset=descIndx[i];
9214 int nbOfSeg=descIndx[i+1]-offset;
9215 for(int j=0;j<nbOfSeg;j++)
9217 int edgeId=desc[offset+j];
9218 int status=cut3DCurve[edgeId];
9222 res.push_back(status);
9225 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9226 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9234 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9240 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9241 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9244 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9248 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9253 {// case when plane is on a multi colinear edge of a polyhedron
9254 if((int)res.size()==2*nbOfSeg)
9256 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9259 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9266 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9267 * 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).
9268 * 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
9269 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9270 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9271 * \param desc is the descending connectivity 3D->3DSurf
9272 * \param descIndx is the descending connectivity index 3D->3DSurf
9274 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9275 const int *desc, const int *descIndx,
9276 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
9278 checkFullyDefined();
9279 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9281 const int *nodal3D=_nodal_connec->getConstPointer();
9282 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9283 int nbOfCells=getNumberOfCells();
9284 for(int i=0;i<nbOfCells;i++)
9286 std::map<int, std::set<int> > m;
9287 int offset=descIndx[i];
9288 int nbOfFaces=descIndx[i+1]-offset;
9291 for(int j=0;j<nbOfFaces;j++)
9293 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9294 if(p.first!=-1 && p.second!=-1)
9298 start=p.first; end=p.second;
9299 m[p.first].insert(p.second);
9300 m[p.second].insert(p.first);
9304 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9305 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9306 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9307 INTERP_KERNEL::NormalizedCellType cmsId;
9308 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9309 start=tmp[0]; end=tmp[nbOfNodesSon-1];
9310 for(unsigned k=0;k<nbOfNodesSon;k++)
9312 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9313 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9320 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9324 std::map<int, std::set<int> >::const_iterator it=m.find(start);
9325 const std::set<int>& s=(*it).second;
9326 std::set<int> s2; s2.insert(prev);
9328 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9331 int val=*s3.begin();
9332 conn.push_back(start);
9339 conn.push_back(end);
9342 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9343 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9344 cellIds->pushBackSilent(i);
9350 * 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
9351 * 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
9352 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9353 * 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
9354 * 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.
9356 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9358 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9360 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9363 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9364 if(cm.getDimension()==2)
9366 const int *node=nodalConnBg+1;
9367 int startNode=*node++;
9368 double refX=coords[2*startNode];
9369 for(;node!=nodalConnEnd;node++)
9371 if(coords[2*(*node)]<refX)
9374 refX=coords[2*startNode];
9377 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9381 double angle0=-M_PI/2;
9386 double angleNext=0.;
9387 while(nextNode!=startNode)
9391 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9393 if(*node!=tmpOut.back() && *node!=prevNode)
9395 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9396 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9401 res=angle0-angleM+2.*M_PI;
9410 if(nextNode!=startNode)
9412 angle0=angleNext-M_PI;
9415 prevNode=tmpOut.back();
9416 tmpOut.push_back(nextNode);
9419 std::vector<int> tmp3(2*(sz-1));
9420 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9421 std::copy(nodalConnBg+1,nodalConnEnd,it);
9422 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9424 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9427 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9429 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9434 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9435 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9440 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9447 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9448 * 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.
9450 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9451 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9452 * \param [in,out] arr array in which the remove operation will be done.
9453 * \param [in,out] arrIndx array in the remove operation will modify
9454 * \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])
9455 * \return true if \b arr and \b arrIndx have been modified, false if not.
9457 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9459 if(!arrIndx || !arr)
9460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9461 if(offsetForRemoval<0)
9462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9463 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9464 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9465 int *arrIPtr=arrIndx->getPointer();
9468 const int *arrPtr=arr->getConstPointer();
9469 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9470 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9472 if(*arrIPtr-previousArrI>offsetForRemoval)
9474 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9476 if(s.find(*work)==s.end())
9477 arrOut.push_back(*work);
9480 previousArrI=*arrIPtr;
9481 *arrIPtr=(int)arrOut.size();
9483 if(arr->getNumberOfTuples()==(int)arrOut.size())
9485 arr->alloc((int)arrOut.size(),1);
9486 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9491 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9492 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9493 * The selection of extraction is done standardly in new2old format.
9494 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9496 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9497 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9498 * \param [in] arrIn arr origin array from which the extraction will be done.
9499 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9500 * \param [out] arrOut the resulting array
9501 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9502 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9504 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9505 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9507 if(!arrIn || !arrIndxIn)
9508 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9509 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9510 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9511 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9512 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9513 const int *arrInPtr=arrIn->getConstPointer();
9514 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9515 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9518 int maxSizeOfArr=arrIn->getNumberOfTuples();
9519 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9520 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9521 arrIo->alloc((int)(sz+1),1);
9522 const int *idsIt=idsOfSelectBg;
9523 int *work=arrIo->getPointer();
9526 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9528 if(*idsIt>=0 && *idsIt<nbOfGrps)
9529 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9532 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9533 throw INTERP_KERNEL::Exception(oss.str().c_str());
9539 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9540 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9541 throw INTERP_KERNEL::Exception(oss.str().c_str());
9544 arro->alloc(lgth,1);
9545 work=arro->getPointer();
9546 idsIt=idsOfSelectBg;
9547 for(std::size_t i=0;i<sz;i++,idsIt++)
9549 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9550 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9553 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9554 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9555 throw INTERP_KERNEL::Exception(oss.str().c_str());
9559 arrIndexOut=arrIo.retn();
9563 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9564 * 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 ).
9565 * The selection of extraction is done standardly in new2old format.
9566 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9568 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9569 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9570 * \param [in] arrIn arr origin array from which the extraction will be done.
9571 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9572 * \param [out] arrOut the resulting array
9573 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9574 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9576 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9577 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9579 if(!arrIn || !arrIndxIn)
9580 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9581 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9582 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9584 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9585 const int *arrInPtr=arrIn->getConstPointer();
9586 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9587 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9589 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9590 int maxSizeOfArr=arrIn->getNumberOfTuples();
9591 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9592 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9593 arrIo->alloc((int)(sz+1),1);
9594 int idsIt=idsOfSelectStart;
9595 int *work=arrIo->getPointer();
9598 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9600 if(idsIt>=0 && idsIt<nbOfGrps)
9601 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9604 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9605 throw INTERP_KERNEL::Exception(oss.str().c_str());
9611 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9612 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9613 throw INTERP_KERNEL::Exception(oss.str().c_str());
9616 arro->alloc(lgth,1);
9617 work=arro->getPointer();
9618 idsIt=idsOfSelectStart;
9619 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9621 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9622 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9625 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9626 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9627 throw INTERP_KERNEL::Exception(oss.str().c_str());
9631 arrIndexOut=arrIo.retn();
9635 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9636 * 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
9637 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9638 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9640 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9641 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9642 * \param [in] arrIn arr origin array from which the extraction will be done.
9643 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9644 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9645 * \param [in] srcArrIndex index array of \b srcArr
9646 * \param [out] arrOut the resulting array
9647 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9649 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9651 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9652 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9653 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9655 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9659 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9660 std::vector<bool> v(nbOfTuples,true);
9662 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9663 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9664 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9666 if(*it>=0 && *it<nbOfTuples)
9669 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9673 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9674 throw INTERP_KERNEL::Exception(oss.str().c_str());
9677 srcArrIndexPtr=srcArrIndex->getConstPointer();
9678 arrIo->alloc(nbOfTuples+1,1);
9679 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9680 const int *arrInPtr=arrIn->getConstPointer();
9681 const int *srcArrPtr=srcArr->getConstPointer();
9682 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9683 int *arroPtr=arro->getPointer();
9684 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9688 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9689 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9693 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9694 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9695 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9699 arrIndexOut=arrIo.retn();
9703 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9704 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9706 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9707 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9708 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9709 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9710 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9711 * \param [in] srcArrIndex index array of \b srcArr
9713 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9715 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9716 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9718 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9720 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9721 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9722 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9723 int *arrInOutPtr=arrInOut->getPointer();
9724 const int *srcArrPtr=srcArr->getConstPointer();
9725 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9727 if(*it>=0 && *it<nbOfTuples)
9729 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9730 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9733 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] !";
9734 throw INTERP_KERNEL::Exception(oss.str().c_str());
9739 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9740 throw INTERP_KERNEL::Exception(oss.str().c_str());
9746 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9747 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9748 * 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]].
9749 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9750 * A negative value in \b arrIn means that it is ignored.
9751 * 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.
9753 * \param [in] arrIn arr origin array from which the extraction will be done.
9754 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9755 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9756 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9758 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9760 int seed=0,nbOfDepthPeelingPerformed=0;
9761 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9765 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9766 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9767 * 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]].
9768 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9769 * A negative value in \b arrIn means that it is ignored.
9770 * 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.
9771 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9772 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9773 * \param [in] arrIn arr origin array from which the extraction will be done.
9774 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9775 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9776 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9777 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9778 * \sa MEDCouplingUMesh::partitionBySpreadZone
9780 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9782 nbOfDepthPeelingPerformed=0;
9784 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9785 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9788 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9792 std::vector<bool> fetched(nbOfTuples,false);
9793 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9796 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9798 nbOfDepthPeelingPerformed=0;
9799 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9800 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9801 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9802 std::vector<bool> fetched2(nbOfTuples,false);
9804 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9806 if(*seedElt>=0 && *seedElt<nbOfTuples)
9807 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9809 { 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()); }
9811 const int *arrInPtr=arrIn->getConstPointer();
9812 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9813 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9814 std::vector<int> idsToFetch1(seedBg,seedEnd);
9815 std::vector<int> idsToFetch2;
9816 std::vector<int> *idsToFetch=&idsToFetch1;
9817 std::vector<int> *idsToFetchOther=&idsToFetch2;
9818 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9820 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9821 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9823 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9824 std::swap(idsToFetch,idsToFetchOther);
9825 idsToFetchOther->clear();
9826 nbOfDepthPeelingPerformed++;
9828 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9831 int *retPtr=ret->getPointer();
9832 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9839 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9840 * 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
9841 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9842 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9844 * \param [in] start begin of set of ids of the input extraction (included)
9845 * \param [in] end end of set of ids of the input extraction (excluded)
9846 * \param [in] step step of the set of ids in range mode.
9847 * \param [in] arrIn arr origin array from which the extraction will be done.
9848 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9849 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9850 * \param [in] srcArrIndex index array of \b srcArr
9851 * \param [out] arrOut the resulting array
9852 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9854 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9856 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9857 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9858 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9860 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9861 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9864 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9866 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9867 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9868 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9870 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9872 if(it>=0 && it<nbOfTuples)
9873 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9876 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9877 throw INTERP_KERNEL::Exception(oss.str().c_str());
9880 srcArrIndexPtr=srcArrIndex->getConstPointer();
9881 arrIo->alloc(nbOfTuples+1,1);
9882 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9883 const int *arrInPtr=arrIn->getConstPointer();
9884 const int *srcArrPtr=srcArr->getConstPointer();
9885 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9886 int *arroPtr=arro->getPointer();
9887 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9889 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9892 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9893 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9897 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9898 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9902 arrIndexOut=arrIo.retn();
9906 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9907 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9909 * \param [in] start begin of set of ids of the input extraction (included)
9910 * \param [in] end end of set of ids of the input extraction (excluded)
9911 * \param [in] step step of the set of ids in range mode.
9912 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9913 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9914 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9915 * \param [in] srcArrIndex index array of \b srcArr
9917 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9919 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9920 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9922 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9924 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9925 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9926 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9927 int *arrInOutPtr=arrInOut->getPointer();
9928 const int *srcArrPtr=srcArr->getConstPointer();
9929 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9931 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9933 if(it>=0 && it<nbOfTuples)
9935 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9936 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9939 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9940 throw INTERP_KERNEL::Exception(oss.str().c_str());
9945 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9946 throw INTERP_KERNEL::Exception(oss.str().c_str());
9952 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9953 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9954 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9955 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9956 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9958 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9960 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9962 checkFullyDefined();
9963 int mdim=getMeshDimension();
9964 int spaceDim=getSpaceDimension();
9966 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9967 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9968 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9969 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9970 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9971 ret->setCoords(getCoords());
9972 ret->allocateCells((int)partition.size());
9974 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9976 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9981 cell=tmp->buildUnionOf2DMesh();
9984 cell=tmp->buildUnionOf3DMesh();
9987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9990 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9993 ret->finishInsertingCells();
9998 * This method partitions \b this into contiguous zone.
9999 * This method only needs a well defined connectivity. Coordinates are not considered here.
10000 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10002 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10004 int nbOfCellsCur=getNumberOfCells();
10005 std::vector<DataArrayInt *> ret;
10006 if(nbOfCellsCur<=0)
10008 DataArrayInt *neigh=0,*neighI=0;
10009 computeNeighborsOfCells(neigh,neighI);
10010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10011 std::vector<bool> fetchedCells(nbOfCellsCur,false);
10012 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10014 while(seed<nbOfCellsCur)
10016 int nbOfPeelPerformed=0;
10017 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10018 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10020 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10021 ret.push_back((*it).retn());
10026 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10027 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10029 * \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.
10030 * \return a newly allocated DataArrayInt to be managed by the caller.
10031 * \throw In case of \a code has not the right format (typically of size 3*n)
10033 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10036 std::size_t nb=code.size()/3;
10037 if(code.size()%3!=0)
10038 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10039 ret->alloc((int)nb,2);
10040 int *retPtr=ret->getPointer();
10041 for(std::size_t i=0;i<nb;i++,retPtr+=2)
10043 retPtr[0]=code[3*i+2];
10044 retPtr[1]=code[3*i+2]+code[3*i+1];
10050 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10051 * All cells in \a this are expected to be linear 3D cells.
10052 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10053 * It leads to an increase to number of cells.
10054 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10055 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
10056 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10058 * \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.
10059 * For all other cells, the splitting policy will be ignored.
10060 * \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.
10061 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10062 * an id of old cell producing it. The caller is to delete this array using
10063 * decrRef() as it is no more needed.
10064 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10066 * \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
10067 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10069 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10070 * \throw If \a this is not fully constituted with linear 3D cells.
10071 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10073 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10075 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10076 checkConnectivityFullyDefined();
10077 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10078 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10079 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10080 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10082 int *retPt(ret->getPointer());
10083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10084 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10085 const int *oldc(_nodal_connec->begin());
10086 const int *oldci(_nodal_connec_index->begin());
10087 const double *coords(_coords->begin());
10088 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10090 std::vector<int> a; std::vector<double> b;
10091 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10092 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10093 const int *aa(&a[0]);
10096 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10098 *it=(-(*(it))-1+nbNodes);
10099 addPts->insertAtTheEnd(b.begin(),b.end());
10100 nbNodes+=(int)b.size()/3;
10102 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10103 newConn->insertAtTheEnd(aa,aa+4);
10105 if(!addPts->empty())
10107 addPts->rearrange(3);
10108 nbOfAdditionalPoints=addPts->getNumberOfTuples();
10109 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10110 ret0->setCoords(addPts);
10114 nbOfAdditionalPoints=0;
10115 ret0->setCoords(getCoords());
10117 ret0->setNodalConnectivity(newConn);
10119 ret->computeOffsets2();
10120 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10121 return ret0.retn();
10125 * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch).
10127 * \sa MEDCouplingUMesh::split2DCells
10129 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10131 checkConnectivityFullyDefined();
10132 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10134 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10135 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10136 int prevPosOfCi(ciPtr[0]);
10137 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10139 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10140 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10141 for(int j=0;j<sz;j++)
10143 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10144 for(int k=0;k<sz2;k++)
10145 *cPtr++=subPtr[offset2+k];
10147 *cPtr++=oldConn[prevPosOfCi+j+2];
10150 prevPosOfCi=ciPtr[1];
10151 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10154 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10155 _nodal_connec->decrRef();
10156 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10159 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10165 int ret(nodesCnter++);
10167 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10168 addCoo.insertAtTheEnd(newPt,newPt+2);
10175 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10178 int trueStart(start>=0?start:nbOfEdges+start);
10179 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
10180 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
10185 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10186 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
10187 middles.push_back(tmp3+offset);
10190 middles.push_back(connBg[trueStart+nbOfEdges]);
10194 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10196 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
10197 newConnOfCell->pushBackSilent(tmpEnd);
10202 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10203 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10204 middles.push_back(tmp3+offset);
10207 middles.push_back(connBg[start+nbOfEdges]);
10211 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10217 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
10218 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10219 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10220 middles.push_back(tmp3+offset);
10223 middles.push_back(connBg[start+nbOfEdges]);
10230 * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
10231 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
10233 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
10235 std::size_t sz(std::distance(connBg,connEnd));
10236 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
10237 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
10239 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
10240 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
10241 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
10242 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
10243 INTERP_KERNEL::NormalizedCellType typeOfSon;
10244 std::vector<int> middles;
10246 for(;nbOfHit<nbs;nbOfTurn++)
10248 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
10249 std::map<INTERP_KERNEL::Node *,int> m;
10250 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10253 unsigned endI(nbs-nbOfHit);
10254 for(unsigned i=0;i<endI;i++)
10256 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
10257 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10258 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
10259 bool isColinear(eint->areColinears());
10271 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
10272 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
10273 for(unsigned ii=0;ii<endII;ii++)
10275 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
10276 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
10277 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
10278 isColinear=eint->areColinears();
10292 //push [posBaseElt,posEndElt) in newConnOfCell using e
10294 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10295 else if(nbOfHit!=nbs)
10296 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10298 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10299 posBaseElt=posEndElt;
10300 for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it=m.begin();it!=m.end();it++)
10301 (*it).first->decrRef();
10304 if(!middles.empty())
10305 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
10310 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10312 * \return int - the number of new nodes created.
10313 * \sa MEDCouplingUMesh::split2DCells
10315 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10318 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10320 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10321 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10322 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10323 const double *oldCoordsPtr(getCoords()->begin());
10324 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10325 int prevPosOfCi(ciPtr[0]);
10326 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10328 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10329 for(int j=0;j<sz;j++)
10330 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10331 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10332 for(int j=0;j<sz;j++)//loop over subedges of oldConn
10334 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10338 cPtr[1]=oldConn[prevPosOfCi+2+j];
10339 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10342 std::vector<INTERP_KERNEL::Node *> ns(3);
10343 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10344 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10345 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10346 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10347 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10349 cPtr[1]=subPtr[offset2+k];
10350 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10352 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10354 { cPtr[1]=tmpEnd; }
10355 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10357 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10358 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10362 _nodal_connec->decrRef();
10363 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10364 addCoo->rearrange(2);
10365 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10367 return addCoo->getNumberOfTuples();
10370 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10371 _own_cell(true),_cell_id(-1),_nb_cell(0)
10376 _nb_cell=mesh->getNumberOfCells();
10380 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10388 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10389 _own_cell(false),_cell_id(bg-1),
10396 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10399 if(_cell_id<_nb_cell)
10408 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10414 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10416 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10419 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10425 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10433 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10439 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10444 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10449 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10451 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10454 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10459 _nb_cell=mesh->getNumberOfCells();
10463 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10470 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10472 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10473 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10474 if(_cell_id<_nb_cell)
10476 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10477 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10478 int startId=_cell_id;
10479 _cell_id+=nbOfElems;
10480 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10486 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10490 _conn=mesh->getNodalConnectivity()->getPointer();
10491 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10495 void MEDCouplingUMeshCell::next()
10497 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10502 _conn_lgth=_conn_indx[1]-_conn_indx[0];
10505 std::string MEDCouplingUMeshCell::repr() const
10507 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10509 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10511 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10515 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10518 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10520 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10521 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10523 return INTERP_KERNEL::NORM_ERROR;
10526 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10529 if(_conn_lgth!=NOTICABLE_FIRST_VAL)