1 // Copyright (C) 2007-2015 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 "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
52 using namespace MEDCoupling;
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
57 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 };
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
62 return new MEDCouplingUMesh;
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
67 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68 ret->setName(meshName);
69 ret->setMeshDimension(meshDim);
74 * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
75 * between \a this and the new mesh.
76 * \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
77 * delete this mesh using decrRef() as it is no more needed.
79 MEDCouplingUMesh *MEDCouplingUMesh::deepCpy() const
86 * Returns a new MEDCouplingUMesh which is a copy of \a this one.
87 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
88 * this mesh are shared by the new mesh.
89 * \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
90 * delete this mesh using decrRef() as it is no more needed.
92 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
94 return new MEDCouplingUMesh(*this,recDeepCpy);
98 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
99 * The coordinates are shared between \a this and the returned instance.
101 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
102 * \sa MEDCouplingUMesh::deepCpy
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCpyConnectivityOnly() const
106 checkConnectivityFullyDefined();
107 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
109 ret->setConnectivity(c,ci);
113 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
116 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
117 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
119 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
120 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
121 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
124 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
126 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
130 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
132 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
133 ret.push_back(_nodal_connec);
134 ret.push_back(_nodal_connec_index);
138 void MEDCouplingUMesh::updateTime() const
140 MEDCouplingPointSet::updateTime();
143 updateTimeWith(*_nodal_connec);
145 if(_nodal_connec_index)
147 updateTimeWith(*_nodal_connec_index);
151 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
156 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
157 * then \a this mesh is most probably is writable, exchangeable and available for most
158 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
159 * this method to check that all is in order with \a this mesh.
160 * \throw If the mesh dimension is not set.
161 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
162 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
163 * \throw If the connectivity data array has more than one component.
164 * \throw If the connectivity data array has a named component.
165 * \throw If the connectivity index data array has more than one component.
166 * \throw If the connectivity index data array has a named component.
168 void MEDCouplingUMesh::checkCoherency() const
171 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
173 MEDCouplingPointSet::checkCoherency();
174 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
176 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
178 std::ostringstream message;
179 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
180 throw INTERP_KERNEL::Exception(message.str().c_str());
185 if(_nodal_connec->getNumberOfComponents()!=1)
186 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
187 if(_nodal_connec->getInfoOnComponent(0)!="")
188 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
192 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
193 if(_nodal_connec_index)
195 if(_nodal_connec_index->getNumberOfComponents()!=1)
196 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
197 if(_nodal_connec_index->getInfoOnComponent(0)!="")
198 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
202 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
206 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
207 * then \a this mesh is most probably is writable, exchangeable and available for all
208 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
209 * method thoroughly checks the nodal connectivity.
210 * \param [in] eps - a not used parameter.
211 * \throw If the mesh dimension is not set.
212 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
213 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
214 * \throw If the connectivity data array has more than one component.
215 * \throw If the connectivity data array has a named component.
216 * \throw If the connectivity index data array has more than one component.
217 * \throw If the connectivity index data array has a named component.
218 * \throw If number of nodes defining an element does not correspond to the type of element.
219 * \throw If the nodal connectivity includes an invalid node id.
221 void MEDCouplingUMesh::checkCoherency1(double eps) const
226 int meshDim=getMeshDimension();
227 int nbOfNodes=getNumberOfNodes();
228 int nbOfCells=getNumberOfCells();
229 const int *ptr=_nodal_connec->getConstPointer();
230 const int *ptrI=_nodal_connec_index->getConstPointer();
231 for(int i=0;i<nbOfCells;i++)
233 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
234 if((int)cm.getDimension()!=meshDim)
236 std::ostringstream oss;
237 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
238 throw INTERP_KERNEL::Exception(oss.str().c_str());
240 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
242 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
244 std::ostringstream oss;
245 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
246 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
247 throw INTERP_KERNEL::Exception(oss.str().c_str());
249 if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
250 if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
252 std::ostringstream oss;
253 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " << nbOfNodesInCell;
254 oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
255 throw INTERP_KERNEL::Exception(oss.str().c_str());
257 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
262 if(nodeId>=nbOfNodes)
264 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
265 throw INTERP_KERNEL::Exception(oss.str().c_str());
270 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
271 throw INTERP_KERNEL::Exception(oss.str().c_str());
275 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
277 std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
278 throw INTERP_KERNEL::Exception(oss.str().c_str());
286 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
287 * elements contained in the mesh. For more info on the mesh dimension see
288 * \ref MEDCouplingUMeshPage.
289 * \param [in] meshDim - a new mesh dimension.
290 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
292 void MEDCouplingUMesh::setMeshDimension(int meshDim)
294 if(meshDim<-1 || meshDim>3)
295 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
301 * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
302 * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
303 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
305 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
307 * \if ENABLE_EXAMPLES
308 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
309 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
312 void MEDCouplingUMesh::allocateCells(int nbOfCells)
315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
316 if(_nodal_connec_index)
318 _nodal_connec_index->decrRef();
322 _nodal_connec->decrRef();
324 _nodal_connec_index=DataArrayInt::New();
325 _nodal_connec_index->reserve(nbOfCells+1);
326 _nodal_connec_index->pushBackSilent(0);
327 _nodal_connec=DataArrayInt::New();
328 _nodal_connec->reserve(2*nbOfCells);
334 * Appends a cell to the connectivity array. For deeper understanding what is
335 * happening see \ref MEDCouplingUMeshNodalConnectivity.
336 * \param [in] type - type of cell to add.
337 * \param [in] size - number of nodes constituting this cell.
338 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
340 * \if ENABLE_EXAMPLES
341 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
342 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
345 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
347 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
348 if(_nodal_connec_index==0)
349 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
350 if((int)cm.getDimension()==_mesh_dim)
353 if(size!=(int)cm.getNumberOfNodes())
355 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
356 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
357 throw INTERP_KERNEL::Exception(oss.str().c_str());
359 int idx=_nodal_connec_index->back();
361 _nodal_connec_index->pushBackSilent(val);
362 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
367 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
368 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
369 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
370 throw INTERP_KERNEL::Exception(oss.str().c_str());
375 * Compacts data arrays to release unused memory. This method is to be called after
376 * finishing cell insertion using \a this->insertNextCell().
378 * \if ENABLE_EXAMPLES
379 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
380 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
383 void MEDCouplingUMesh::finishInsertingCells()
385 _nodal_connec->pack();
386 _nodal_connec_index->pack();
387 _nodal_connec->declareAsNew();
388 _nodal_connec_index->declareAsNew();
393 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
394 * Useful for python users.
396 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
398 return new MEDCouplingUMeshCellIterator(this);
402 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
403 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
404 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
405 * Useful for python users.
407 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
409 if(!checkConsecutiveCellTypes())
410 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
411 return new MEDCouplingUMeshCellByTypeEntry(this);
415 * Returns a set of all cell types available in \a this mesh.
416 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
417 * \warning this method does not throw any exception even if \a this is not defined.
418 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
420 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
426 * This method returns the sorted list of geometric types in \a this.
427 * 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
428 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
430 * \throw if connectivity in \a this is not correctly defined.
432 * \sa MEDCouplingMesh::getAllGeoTypes
434 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
436 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
437 checkConnectivityFullyDefined();
438 int nbOfCells(getNumberOfCells());
441 if(getMeshLength()<1)
442 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
443 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
444 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
445 for(int i=1;i<nbOfCells;i++,ci++)
446 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
447 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
452 * This method is a method that compares \a this and \a other.
453 * This method compares \b all attributes, even names and component names.
455 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
458 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
459 std::ostringstream oss; oss.precision(15);
460 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
463 reason="mesh given in input is not castable in MEDCouplingUMesh !";
466 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
468 if(_mesh_dim!=otherC->_mesh_dim)
470 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
474 if(_types!=otherC->_types)
476 oss << "umesh geometric type mismatch :\nThis geometric types are :";
477 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
478 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
479 oss << "\nOther geometric types are :";
480 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
481 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
485 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
486 if(_nodal_connec==0 || otherC->_nodal_connec==0)
488 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
491 if(_nodal_connec!=otherC->_nodal_connec)
492 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
494 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
497 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
498 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
500 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
503 if(_nodal_connec_index!=otherC->_nodal_connec_index)
504 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
506 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
513 * Checks if data arrays of this mesh (node coordinates, nodal
514 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
516 * \param [in] other - the mesh to compare with.
517 * \param [in] prec - precision value used to compare node coordinates.
518 * \return bool - \a true if the two meshes are same.
520 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
522 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
525 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
527 if(_mesh_dim!=otherC->_mesh_dim)
529 if(_types!=otherC->_types)
531 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
532 if(_nodal_connec==0 || otherC->_nodal_connec==0)
534 if(_nodal_connec!=otherC->_nodal_connec)
535 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
537 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
538 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
540 if(_nodal_connec_index!=otherC->_nodal_connec_index)
541 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
547 * Checks if \a this and \a other meshes are geometrically equivalent with high
548 * probability, else an exception is thrown. The meshes are considered equivalent if
549 * (1) meshes contain the same number of nodes and the same number of elements of the
550 * same types (2) three cells of the two meshes (first, last and middle) are based
551 * on coincident nodes (with a specified precision).
552 * \param [in] other - the mesh to compare with.
553 * \param [in] prec - the precision used to compare nodes of the two meshes.
554 * \throw If the two meshes do not match.
556 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
558 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
559 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
561 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
565 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
566 * cells each node belongs to.
567 * \warning For speed reasons, this method does not check if node ids in the nodal
568 * connectivity correspond to the size of node coordinates array.
569 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
570 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
571 * dividing cell ids in \a revNodal into groups each referring to one
572 * node. Its every element (except the last one) is an index pointing to the
573 * first id of a group of cells. For example cells sharing the node #1 are
574 * described by following range of indices:
575 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
576 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
577 * Number of cells sharing the *i*-th node is
578 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
579 * \throw If the coordinates array is not set.
580 * \throw If the nodal connectivity of cells is not defined.
582 * \if ENABLE_EXAMPLES
583 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
584 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
587 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
590 int nbOfNodes=getNumberOfNodes();
591 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
592 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
593 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
594 const int *conn=_nodal_connec->getConstPointer();
595 const int *connIndex=_nodal_connec_index->getConstPointer();
596 int nbOfCells=getNumberOfCells();
597 int nbOfEltsInRevNodal=0;
598 for(int eltId=0;eltId<nbOfCells;eltId++)
600 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
601 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
602 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
603 if(*iter>=0)//for polyhedrons
605 nbOfEltsInRevNodal++;
606 revNodalIndxPtr[(*iter)+1]++;
609 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
610 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
611 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
612 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
613 for(int eltId=0;eltId<nbOfCells;eltId++)
615 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
616 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
617 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
618 if(*iter>=0)//for polyhedrons
619 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
625 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
630 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
636 if(cm.getOrientationStatus(nb,conn1,conn2))
643 class MinusOneSonsGenerator
646 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
647 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
648 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
649 static const int DELTA=1;
651 const INTERP_KERNEL::CellModel& _cm;
654 class MinusOneSonsGeneratorBiQuadratic
657 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
658 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
659 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
660 static const int DELTA=1;
662 const INTERP_KERNEL::CellModel& _cm;
665 class MinusTwoSonsGenerator
668 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
669 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
670 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
671 static const int DELTA=2;
673 const INTERP_KERNEL::CellModel& _cm;
679 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
680 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
681 * describing correspondence between cells of \a this and the result meshes are
682 * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
683 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
684 * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
685 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
686 * \warning For speed reasons, this method does not check if node ids in the nodal
687 * connectivity correspond to the size of node coordinates array.
688 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
689 * to write this mesh to the MED file, its cells must be sorted using
690 * sortCellsInMEDFileFrmt().
691 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
692 * each cell of \a this mesh.
693 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
694 * dividing cell ids in \a desc into groups each referring to one
695 * cell of \a this mesh. Its every element (except the last one) is an index
696 * pointing to the first id of a group of cells. For example cells of the
697 * result mesh bounding the cell #1 of \a this mesh are described by following
699 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
700 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
701 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
702 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
703 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
704 * by each cell of the result mesh.
705 * \param [in,out] revDescIndx - the array, of length one more than number of cells
706 * in the result mesh,
707 * dividing cell ids in \a revDesc into groups each referring to one
708 * cell of the result mesh the same way as \a descIndx divides \a desc.
709 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
710 * delete this mesh using decrRef() as it is no more needed.
711 * \throw If the coordinates array is not set.
712 * \throw If the nodal connectivity of cells is node defined.
713 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
714 * revDescIndx == NULL.
716 * \if ENABLE_EXAMPLES
717 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
718 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
720 * \sa buildDescendingConnectivity2()
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
724 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
728 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732 * \sa MEDCouplingUMesh::buildDescendingConnectivity
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
737 if(getMeshDimension()!=3)
738 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
743 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744 * this->getMeshDimension(), that bound cells of \a this mesh. In
745 * addition arrays describing correspondence between cells of \a this and the result
746 * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
747 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748 * mesh. This method differs from buildDescendingConnectivity() in that apart
749 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750 * result meshes. So a positive id means that order of nodes in corresponding cells
751 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753 * i.e. cell ids are one-based.
754 * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
755 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
756 * \warning For speed reasons, this method does not check if node ids in the nodal
757 * connectivity correspond to the size of node coordinates array.
758 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759 * to write this mesh to the MED file, its cells must be sorted using
760 * sortCellsInMEDFileFrmt().
761 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
762 * each cell of \a this mesh.
763 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764 * dividing cell ids in \a desc into groups each referring to one
765 * cell of \a this mesh. Its every element (except the last one) is an index
766 * pointing to the first id of a group of cells. For example cells of the
767 * result mesh bounding the cell #1 of \a this mesh are described by following
769 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774 * by each cell of the result mesh.
775 * \param [in,out] revDescIndx - the array, of length one more than number of cells
776 * in the result mesh,
777 * dividing cell ids in \a revDesc into groups each referring to one
778 * cell of the result mesh the same way as \a descIndx divides \a desc.
779 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780 * shares the node coordinates array with \a this mesh. The caller is to
781 * delete this mesh using decrRef() as it is no more needed.
782 * \throw If the coordinates array is not set.
783 * \throw If the nodal connectivity of cells is node defined.
784 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785 * revDescIndx == NULL.
787 * \if ENABLE_EXAMPLES
788 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
789 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
791 * \sa buildDescendingConnectivity()
793 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
795 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
799 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
800 * For speed reasons no check of this will be done. This method calls
801 * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
802 * This method lists cell by cell in \b this which are its neighbors. To compute the result
803 * only connectivities are considered.
804 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
805 * The format of return is hence \ref numbering-indirect.
807 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
808 * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
809 * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
810 * is equal to the last values in \b neighborsIndx.
811 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
812 * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
814 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
820 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
822 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
826 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
827 * of MEDCouplingUMesh::computeNeighborsOfCells.
828 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
829 * typically the case to extract a set a neighbours,
830 * excluding a set of meshdim-1 cells in input descending connectivity.
831 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
832 * the result of MEDCouplingUMesh::buildDescendingConnectivity.
833 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
835 * The neighbor cells of cell having id 'cellId' 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 (\ref numbering-indirect).
839 * \param [in] revDesc reverse descending connectivity array.
840 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
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)
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();
876 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
877 * For speed reasons no check of this will be done. This method calls
878 * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
879 * This method lists node by node in \b this which are its neighbors. To compute the result
880 * only connectivities are considered.
881 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
883 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
884 * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
885 * parameter allows to select the right part in this array (\ref numbering-indirect).
886 * The number of tuples is equal to the last values in \b neighborsIndx.
887 * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
888 * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
890 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
893 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
895 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
900 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
905 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
910 mesh1D=const_cast<MEDCouplingUMesh *>(this);
916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
919 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
920 mesh1D->getReverseNodalConnectivity(desc,descIndx);
921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
922 ret0->alloc(desc->getNumberOfTuples(),1);
923 int *r0Pt(ret0->getPointer());
924 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
925 for(int i=0;i<nbNodes;i++,rni++)
927 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
928 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
930 neighbors=ret0.retn();
931 neighborsIdx=descIndx.retn();
937 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
938 * For speed reasons no check of this will be done.
940 template<class SonsGenerator>
941 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
943 if(!desc || !descIndx || !revDesc || !revDescIndx)
944 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
945 checkConnectivityFullyDefined();
946 int nbOfCells=getNumberOfCells();
947 int nbOfNodes=getNumberOfNodes();
948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
949 int *revNodalIndxPtr=revNodalIndx->getPointer();
950 const int *conn=_nodal_connec->getConstPointer();
951 const int *connIndex=_nodal_connec_index->getConstPointer();
952 std::string name="Mesh constituent of "; name+=getName();
953 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
954 ret->setCoords(getCoords());
955 ret->allocateCells(2*nbOfCells);
956 descIndx->alloc(nbOfCells+1,1);
957 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
958 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
959 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
961 int pos=connIndex[eltId];
962 int posP1=connIndex[eltId+1];
963 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
964 SonsGenerator sg(cm);
965 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
966 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
967 for(unsigned i=0;i<nbOfSons;i++)
969 INTERP_KERNEL::NormalizedCellType cmsId;
970 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
971 for(unsigned k=0;k<nbOfNodesSon;k++)
973 revNodalIndxPtr[tmp[k]+1]++;
974 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
975 revDesc2->pushBackSilent(eltId);
977 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
979 int nbOfCellsM1=ret->getNumberOfCells();
980 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
982 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
983 int *revNodalPtr=revNodal->getPointer();
984 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
985 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
986 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
988 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
989 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
990 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
991 if(*iter>=0)//for polyhedrons
992 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
995 DataArrayInt *commonCells=0,*commonCellsI=0;
996 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
997 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
998 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
999 int newNbOfCellsM1=-1;
1000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1001 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1002 std::vector<bool> isImpacted(nbOfCellsM1,false);
1003 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1004 for(int work2=work[0];work2!=work[1];work2++)
1005 isImpacted[commonCellsPtr[work2]]=true;
1006 const int *o2nM1Ptr=o2nM1->getConstPointer();
1007 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1008 const int *n2oM1Ptr=n2oM1->getConstPointer();
1009 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1010 ret2->copyTinyInfoFrom(this);
1011 desc->alloc(descIndx->back(),1);
1012 int *descPtr=desc->getPointer();
1013 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1014 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1017 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1020 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1022 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1023 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1026 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1029 revDesc->reserve(newNbOfCellsM1);
1030 revDescIndx->alloc(newNbOfCellsM1+1,1);
1031 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1032 const int *revDesc2Ptr=revDesc2->getConstPointer();
1033 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1035 int oldCellIdM1=n2oM1Ptr[i];
1036 if(!isImpacted[oldCellIdM1])
1038 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1039 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1043 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1044 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1045 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1053 struct MEDCouplingAccVisit
1055 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1056 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1057 int _new_nb_of_nodes;
1063 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1064 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1065 * array of cell ids. Pay attention that after conversion all algorithms work slower
1066 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1067 * conversion due presence of invalid ids in the array of cells to convert, as a
1068 * result \a this mesh contains some already converted elements. In this case the 2D
1069 * mesh remains valid but 3D mesh becomes \b inconsistent!
1070 * \warning This method can significantly modify the order of geometric types in \a this,
1071 * hence, to write this mesh to the MED file, its cells must be sorted using
1072 * sortCellsInMEDFileFrmt().
1073 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1074 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1075 * cellIdsToConvertBg.
1076 * \throw If the coordinates array is not set.
1077 * \throw If the nodal connectivity of cells is node defined.
1078 * \throw If dimension of \a this mesh is not either 2 or 3.
1080 * \if ENABLE_EXAMPLES
1081 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1082 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1085 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1087 checkFullyDefined();
1088 int dim=getMeshDimension();
1090 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1091 int nbOfCells(getNumberOfCells());
1094 const int *connIndex=_nodal_connec_index->getConstPointer();
1095 int *conn=_nodal_connec->getPointer();
1096 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1098 if(*iter>=0 && *iter<nbOfCells)
1100 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1101 if(!cm.isQuadratic())
1102 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1104 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1108 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1109 oss << " in range [0," << nbOfCells << ") !";
1110 throw INTERP_KERNEL::Exception(oss.str().c_str());
1116 int *connIndex(_nodal_connec_index->getPointer());
1117 const int *connOld(_nodal_connec->getConstPointer());
1118 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1119 std::vector<bool> toBeDone(nbOfCells,false);
1120 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1122 if(*iter>=0 && *iter<nbOfCells)
1123 toBeDone[*iter]=true;
1126 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1127 oss << " in range [0," << nbOfCells << ") !";
1128 throw INTERP_KERNEL::Exception(oss.str().c_str());
1131 for(int cellId=0;cellId<nbOfCells;cellId++)
1133 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1134 int lgthOld(posP1-pos-1);
1135 if(toBeDone[cellId])
1137 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1138 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1139 int *tmp(new int[nbOfFaces*lgthOld+1]);
1140 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1141 for(unsigned j=0;j<nbOfFaces;j++)
1143 INTERP_KERNEL::NormalizedCellType type;
1144 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1148 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1149 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1150 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1155 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1156 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1159 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1165 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1166 * polyhedrons (if \a this is a 3D mesh).
1167 * \warning As this method is purely for user-friendliness and no optimization is
1168 * done to avoid construction of a useless vector, this method can be costly
1170 * \throw If the coordinates array is not set.
1171 * \throw If the nodal connectivity of cells is node defined.
1172 * \throw If dimension of \a this mesh is not either 2 or 3.
1174 void MEDCouplingUMesh::convertAllToPoly()
1176 int nbOfCells=getNumberOfCells();
1177 std::vector<int> cellIds(nbOfCells);
1178 for(int i=0;i<nbOfCells;i++)
1180 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1184 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1185 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1186 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1187 * base facet of the volume and the second half of nodes describes an opposite facet
1188 * having the same number of nodes as the base one. This method converts such
1189 * connectivity to a valid polyhedral format where connectivity of each facet is
1190 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1191 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1192 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1193 * a correct orientation of the first facet of a polyhedron, else orientation of a
1194 * corrected cell is reverse.<br>
1195 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1196 * it releases the user from boring description of polyhedra connectivity in the valid
1198 * \throw If \a this->getMeshDimension() != 3.
1199 * \throw If \a this->getSpaceDimension() != 3.
1200 * \throw If the nodal connectivity of cells is not defined.
1201 * \throw If the coordinates array is not set.
1202 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1203 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1205 * \if ENABLE_EXAMPLES
1206 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1207 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1210 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1212 checkFullyDefined();
1213 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1214 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1215 int nbOfCells=getNumberOfCells();
1216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1217 newCi->alloc(nbOfCells+1,1);
1218 int *newci=newCi->getPointer();
1219 const int *ci=_nodal_connec_index->getConstPointer();
1220 const int *c=_nodal_connec->getConstPointer();
1222 for(int i=0;i<nbOfCells;i++)
1224 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1225 if(type==INTERP_KERNEL::NORM_POLYHED)
1227 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1229 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1230 throw INTERP_KERNEL::Exception(oss.str().c_str());
1232 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1235 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 !";
1236 throw INTERP_KERNEL::Exception(oss.str().c_str());
1239 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)
1242 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1245 newC->alloc(newci[nbOfCells],1);
1246 int *newc=newC->getPointer();
1247 for(int i=0;i<nbOfCells;i++)
1249 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1250 if(type==INTERP_KERNEL::NORM_POLYHED)
1252 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1253 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1255 for(std::size_t j=0;j<n1;j++)
1257 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1259 newc[n1+5*j+1]=c[ci[i]+1+j];
1260 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1261 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1262 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1267 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1269 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1270 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1275 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1276 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1277 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1278 * to write this mesh to the MED file, its cells must be sorted using
1279 * sortCellsInMEDFileFrmt().
1280 * \return \c true if at least one cell has been converted, \c false else. In the
1281 * last case the nodal connectivity remains unchanged.
1282 * \throw If the coordinates array is not set.
1283 * \throw If the nodal connectivity of cells is not defined.
1284 * \throw If \a this->getMeshDimension() < 0.
1286 bool MEDCouplingUMesh::unPolyze()
1288 checkFullyDefined();
1289 int mdim=getMeshDimension();
1291 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1294 int nbOfCells=getNumberOfCells();
1297 int initMeshLgth=getMeshLength();
1298 int *conn=_nodal_connec->getPointer();
1299 int *index=_nodal_connec_index->getPointer();
1304 for(int i=0;i<nbOfCells;i++)
1306 lgthOfCurCell=index[i+1]-posOfCurCell;
1307 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1308 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1309 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1313 switch(cm.getDimension())
1317 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1318 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1319 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1324 int nbOfFaces,lgthOfPolyhConn;
1325 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1326 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1331 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1335 ret=ret || (newType!=type);
1336 conn[newPos]=newType;
1338 posOfCurCell=index[i+1];
1343 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1344 newPos+=lgthOfCurCell;
1345 posOfCurCell+=lgthOfCurCell;
1349 if(newPos!=initMeshLgth)
1350 _nodal_connec->reAlloc(newPos);
1357 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1358 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1359 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1361 * \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
1364 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1366 checkFullyDefined();
1367 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1369 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1370 coords->recenterForMaxPrecision(eps);
1372 int nbOfCells=getNumberOfCells();
1373 const int *conn=_nodal_connec->getConstPointer();
1374 const int *index=_nodal_connec_index->getConstPointer();
1375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1376 connINew->alloc(nbOfCells+1,1);
1377 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1380 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1382 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1384 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1388 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1389 *connINewPtr=connNew->getNumberOfTuples();
1392 setConnectivity(connNew,connINew,false);
1396 * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1397 * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1398 * the format of the returned DataArrayInt instance.
1400 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1401 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1403 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1405 checkConnectivityFullyDefined();
1406 int nbOfCells=getNumberOfCells();
1407 const int *connIndex=_nodal_connec_index->getConstPointer();
1408 const int *conn=_nodal_connec->getConstPointer();
1409 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1410 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1411 std::vector<bool> retS(maxElt,false);
1412 for(int i=0;i<nbOfCells;i++)
1413 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1417 for(int i=0;i<maxElt;i++)
1420 DataArrayInt *ret=DataArrayInt::New();
1422 int *retPtr=ret->getPointer();
1423 for(int i=0;i<maxElt;i++)
1430 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1431 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1433 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1435 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1436 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1437 for(int i=0;i<nbOfCells;i++)
1438 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1441 if(conn[j]<nbOfNodes)
1442 nodeIdsInUse[conn[j]]=true;
1445 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1446 throw INTERP_KERNEL::Exception(oss.str().c_str());
1452 * Finds nodes not used in any cell and returns an array giving a new id to every node
1453 * by excluding the unused nodes, for which the array holds -1. The result array is
1454 * a mapping in "Old to New" mode.
1455 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1456 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1457 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1458 * if the node is unused or a new id else. The caller is to delete this
1459 * array using decrRef() as it is no more needed.
1460 * \throw If the coordinates array is not set.
1461 * \throw If the nodal connectivity of cells is not defined.
1462 * \throw If the nodal connectivity includes an invalid id.
1464 * \if ENABLE_EXAMPLES
1465 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1466 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1468 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1470 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1473 int nbOfNodes(getNumberOfNodes());
1474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1475 ret->alloc(nbOfNodes,1);
1476 int *traducer=ret->getPointer();
1477 std::fill(traducer,traducer+nbOfNodes,-1);
1478 int nbOfCells=getNumberOfCells();
1479 const int *connIndex=_nodal_connec_index->getConstPointer();
1480 const int *conn=_nodal_connec->getConstPointer();
1481 for(int i=0;i<nbOfCells;i++)
1482 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1485 if(conn[j]<nbOfNodes)
1486 traducer[conn[j]]=1;
1489 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1490 throw INTERP_KERNEL::Exception(oss.str().c_str());
1493 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1494 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1499 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1500 * For each cell in \b this the number of nodes constituting cell is computed.
1501 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1502 * So for pohyhedrons some nodes can be counted several times in the returned result.
1504 * \return a newly allocated array
1505 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1507 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1509 checkConnectivityFullyDefined();
1510 int nbOfCells=getNumberOfCells();
1511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1512 ret->alloc(nbOfCells,1);
1513 int *retPtr=ret->getPointer();
1514 const int *conn=getNodalConnectivity()->getConstPointer();
1515 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1516 for(int i=0;i<nbOfCells;i++,retPtr++)
1518 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1519 *retPtr=connI[i+1]-connI[i]-1;
1521 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1527 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1528 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1530 * \return DataArrayInt * - new object to be deallocated by the caller.
1531 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1533 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1535 checkConnectivityFullyDefined();
1536 int nbOfCells=getNumberOfCells();
1537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1538 ret->alloc(nbOfCells,1);
1539 int *retPtr=ret->getPointer();
1540 const int *conn=getNodalConnectivity()->getConstPointer();
1541 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1542 for(int i=0;i<nbOfCells;i++,retPtr++)
1544 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1545 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1546 *retPtr=(int)s.size();
1550 *retPtr=(int)s.size();
1557 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1558 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1560 * \return a newly allocated array
1562 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1564 checkConnectivityFullyDefined();
1565 int nbOfCells=getNumberOfCells();
1566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1567 ret->alloc(nbOfCells,1);
1568 int *retPtr=ret->getPointer();
1569 const int *conn=getNodalConnectivity()->getConstPointer();
1570 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1571 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1573 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1574 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1580 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1581 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1582 * array mean that the corresponding old node is no more used.
1583 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1584 * this->getNumberOfNodes() before call of this method. The caller is to
1585 * delete this array using decrRef() as it is no more needed.
1586 * \throw If the coordinates array is not set.
1587 * \throw If the nodal connectivity of cells is not defined.
1588 * \throw If the nodal connectivity includes an invalid id.
1589 * \sa areAllNodesFetched
1591 * \if ENABLE_EXAMPLES
1592 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1593 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1596 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1598 return MEDCouplingPointSet::zipCoordsTraducer();
1602 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1603 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1605 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1610 return AreCellsEqual0(conn,connI,cell1,cell2);
1612 return AreCellsEqual1(conn,connI,cell1,cell2);
1614 return AreCellsEqual2(conn,connI,cell1,cell2);
1616 return AreCellsEqual3(conn,connI,cell1,cell2);
1618 return AreCellsEqual7(conn,connI,cell1,cell2);
1620 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1624 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1626 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1628 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1629 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1634 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1636 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1638 int sz=connI[cell1+1]-connI[cell1];
1639 if(sz==connI[cell2+1]-connI[cell2])
1641 if(conn[connI[cell1]]==conn[connI[cell2]])
1643 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1644 unsigned dim=cm.getDimension();
1650 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1651 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1652 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1653 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1654 return work!=tmp+sz1?1:0;
1657 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1660 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1667 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1669 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1671 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1673 if(conn[connI[cell1]]==conn[connI[cell2]])
1675 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1676 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1684 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1686 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1688 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1690 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1691 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1698 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1700 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1702 int sz=connI[cell1+1]-connI[cell1];
1703 if(sz==connI[cell2+1]-connI[cell2])
1705 if(conn[connI[cell1]]==conn[connI[cell2]])
1707 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1708 unsigned dim=cm.getDimension();
1714 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1715 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1716 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1717 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1722 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1723 std::reverse_iterator<int *> it2((int *)tmp);
1724 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1730 return work!=tmp+sz1?1:0;
1733 {//case of SEG2 and SEG3
1734 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1736 if(!cm.isQuadratic())
1738 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1739 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1740 if(std::equal(it1,it2,conn+connI[cell2]+1))
1746 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])
1753 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1760 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1761 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1762 * and result remains unchanged.
1763 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1764 * If in 'candidates' pool -1 value is considered as an empty value.
1765 * WARNING this method returns only ONE set of result !
1767 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1769 if(candidates.size()<1)
1772 std::vector<int>::const_iterator iter=candidates.begin();
1773 int start=(*iter++);
1774 for(;iter!=candidates.end();iter++)
1776 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1781 result->pushBackSilent(start);
1785 result->pushBackSilent(*iter);
1787 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1794 * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1796 * This method keeps the coordiantes of \a this. This method is time consuming.
1798 * \param [in] compType input specifying the technique used to compare cells each other.
1799 * - 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.
1800 * - 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)
1801 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1802 * - 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
1803 * can be used for users not sensitive to orientation of cell
1804 * \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.
1805 * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1806 * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1807 * \return the correspondance array old to new in a newly allocated array.
1810 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1813 getReverseNodalConnectivity(revNodal,revNodalI);
1814 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1817 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1818 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1821 int nbOfCells=nodalI->getNumberOfTuples()-1;
1822 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1823 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1824 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1825 std::vector<bool> isFetched(nbOfCells,false);
1828 for(int i=0;i<nbOfCells;i++)
1832 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1833 std::vector<int> v,v2;
1834 if(connOfNode!=connPtr+connIPtr[i+1])
1836 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1837 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1840 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1844 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1845 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1846 v2.resize(std::distance(v2.begin(),it));
1850 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1852 int pos=commonCellsI->back();
1853 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1854 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1855 isFetched[*it]=true;
1863 for(int i=startCellId;i<nbOfCells;i++)
1867 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1868 std::vector<int> v,v2;
1869 if(connOfNode!=connPtr+connIPtr[i+1])
1871 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1874 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1878 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1879 v2.resize(std::distance(v2.begin(),it));
1883 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1885 int pos=commonCellsI->back();
1886 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1887 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1888 isFetched[*it]=true;
1894 commonCellsArr=commonCells.retn();
1895 commonCellsIArr=commonCellsI.retn();
1899 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1900 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1901 * than \a other->getNumberOfCells() in the returned array means that there is no
1902 * corresponding cell in \a this mesh.
1903 * It is expected that \a this and \a other meshes share the same node coordinates
1904 * array, if it is not so an exception is thrown.
1905 * \param [in] other - the mesh to compare with.
1906 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1907 * valid values [0,1,2], see zipConnectivityTraducer().
1908 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1909 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1910 * values. The caller is to delete this array using
1911 * decrRef() as it is no more needed.
1912 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1915 * \if ENABLE_EXAMPLES
1916 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1917 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1919 * \sa checkDeepEquivalOnSameNodesWith()
1920 * \sa checkGeoEquivalWith()
1922 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1924 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1925 int nbOfCells=getNumberOfCells();
1926 static const int possibleCompType[]={0,1,2};
1927 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1929 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1930 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1932 throw INTERP_KERNEL::Exception(oss.str().c_str());
1934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1935 arr=o2n->substr(nbOfCells);
1936 arr->setName(other->getName());
1938 if(other->getNumberOfCells()==0)
1940 return arr->getMaxValue(tmp)<nbOfCells;
1944 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1945 * This method tries to determine if \b other is fully included in \b this.
1946 * The main difference is that this method is not expected to throw exception.
1947 * This method has two outputs :
1949 * \param other other mesh
1950 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1951 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1953 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1955 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1956 DataArrayInt *commonCells=0,*commonCellsI=0;
1957 int thisNbCells=getNumberOfCells();
1958 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1960 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1961 int otherNbCells=other->getNumberOfCells();
1962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1963 arr2->alloc(otherNbCells,1);
1964 arr2->fillWithZero();
1965 int *arr2Ptr=arr2->getPointer();
1966 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1967 for(int i=0;i<nbOfCommon;i++)
1969 int start=commonCellsPtr[commonCellsIPtr[i]];
1970 if(start<thisNbCells)
1972 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1974 int sig=commonCellsPtr[j]>0?1:-1;
1975 int val=std::abs(commonCellsPtr[j])-1;
1976 if(val>=thisNbCells)
1977 arr2Ptr[val-thisNbCells]=sig*(start+1);
1981 arr2->setName(other->getName());
1982 if(arr2->presenceOfValue(0))
1988 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1991 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1992 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1994 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1995 std::vector<const MEDCouplingUMesh *> ms(2);
1998 return MergeUMeshesOnSameCoords(ms);
2002 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2003 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2004 * cellIds is not given explicitely but by a range python like.
2009 * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2010 * \return a newly allocated
2012 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2013 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2015 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2017 if(getMeshDimension()!=-1)
2018 return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords));
2021 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2023 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2025 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2027 return const_cast<MEDCouplingUMesh *>(this);
2032 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2033 * The result mesh shares or not the node coordinates array with \a this mesh depending
2034 * on \a keepCoords parameter.
2035 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2036 * to write this mesh to the MED file, its cells must be sorted using
2037 * sortCellsInMEDFileFrmt().
2038 * \param [in] begin - an array of cell ids to include to the new mesh.
2039 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2040 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2041 * array of \a this mesh, else "free" nodes are removed from the result mesh
2042 * by calling zipCoords().
2043 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2044 * to delete this mesh using decrRef() as it is no more needed.
2045 * \throw If the coordinates array is not set.
2046 * \throw If the nodal connectivity of cells is not defined.
2047 * \throw If any cell id in the array \a begin is not valid.
2049 * \if ENABLE_EXAMPLES
2050 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2051 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2054 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2056 if(getMeshDimension()!=-1)
2057 return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2061 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2063 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2065 return const_cast<MEDCouplingUMesh *>(this);
2070 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2072 * 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.
2073 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2074 * The number of cells of \b this will remain the same with this method.
2076 * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2077 * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2078 * \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 ).
2079 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2081 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2083 checkConnectivityFullyDefined();
2084 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2085 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2086 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2087 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2089 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2090 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2091 throw INTERP_KERNEL::Exception(oss.str().c_str());
2093 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2094 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2096 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2097 throw INTERP_KERNEL::Exception(oss.str().c_str());
2099 int nbOfCells=getNumberOfCells();
2100 bool easyAssign=true;
2101 const int *connI=_nodal_connec_index->getConstPointer();
2102 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2103 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2105 if(*it>=0 && *it<nbOfCells)
2107 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2111 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2112 throw INTERP_KERNEL::Exception(oss.str().c_str());
2117 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2122 DataArrayInt *arrOut=0,*arrIOut=0;
2123 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2126 setConnectivity(arrOut,arrIOut,true);
2130 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2132 checkConnectivityFullyDefined();
2133 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2134 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2135 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2136 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2138 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2139 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2140 throw INTERP_KERNEL::Exception(oss.str().c_str());
2142 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2143 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2145 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2146 throw INTERP_KERNEL::Exception(oss.str().c_str());
2148 int nbOfCells=getNumberOfCells();
2149 bool easyAssign=true;
2150 const int *connI=_nodal_connec_index->getConstPointer();
2151 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2153 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2155 if(it>=0 && it<nbOfCells)
2157 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2161 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2162 throw INTERP_KERNEL::Exception(oss.str().c_str());
2167 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2172 DataArrayInt *arrOut=0,*arrIOut=0;
2173 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2176 setConnectivity(arrOut,arrIOut,true);
2181 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2182 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2183 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2184 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2186 * \param [in] begin input start of array of node ids.
2187 * \param [in] end input end of array of node ids.
2188 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2189 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2191 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2193 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2194 checkConnectivityFullyDefined();
2196 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2197 std::vector<bool> fastFinder(sz,false);
2198 for(const int *work=begin;work!=end;work++)
2199 if(*work>=0 && *work<sz)
2200 fastFinder[*work]=true;
2201 int nbOfCells=getNumberOfCells();
2202 const int *conn=getNodalConnectivity()->getConstPointer();
2203 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2204 for(int i=0;i<nbOfCells;i++)
2206 int ref=0,nbOfHit=0;
2207 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2211 if(fastFinder[*work2])
2214 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2215 cellIdsKept->pushBackSilent(i);
2217 cellIdsKeptArr=cellIdsKept.retn();
2221 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2222 * this->getMeshDimension(), that bound some cells of \a this mesh.
2223 * The cells of lower dimension to include to the result mesh are selected basing on
2224 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2225 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2226 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2227 * created mesh shares the node coordinates array with \a this mesh.
2228 * \param [in] begin - the array of node ids.
2229 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2230 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2231 * array \a begin are added, else cells whose any node is in the
2232 * array \a begin are added.
2233 * \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2234 * to delete this mesh using decrRef() as it is no more needed.
2235 * \throw If the coordinates array is not set.
2236 * \throw If the nodal connectivity of cells is not defined.
2237 * \throw If any node id in \a begin is not valid.
2239 * \if ENABLE_EXAMPLES
2240 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2241 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2244 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2247 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2248 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2249 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2250 return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2254 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2255 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2256 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2257 * array of \a this mesh, else "free" nodes are removed from the result mesh
2258 * by calling zipCoords().
2259 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2260 * to delete this mesh using decrRef() as it is no more needed.
2261 * \throw If the coordinates array is not set.
2262 * \throw If the nodal connectivity of cells is not defined.
2264 * \if ENABLE_EXAMPLES
2265 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2266 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2269 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2271 DataArrayInt *desc=DataArrayInt::New();
2272 DataArrayInt *descIndx=DataArrayInt::New();
2273 DataArrayInt *revDesc=DataArrayInt::New();
2274 DataArrayInt *revDescIndx=DataArrayInt::New();
2276 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2279 descIndx->decrRef();
2280 int nbOfCells=meshDM1->getNumberOfCells();
2281 const int *revDescIndxC=revDescIndx->getConstPointer();
2282 std::vector<int> boundaryCells;
2283 for(int i=0;i<nbOfCells;i++)
2284 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2285 boundaryCells.push_back(i);
2286 revDescIndx->decrRef();
2287 MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2292 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2293 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2294 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2296 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2298 checkFullyDefined();
2299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2304 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2305 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2309 const int *revDescPtr=revDesc->getConstPointer();
2310 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2311 int nbOfCells=getNumberOfCells();
2312 std::vector<bool> ret1(nbOfCells,false);
2314 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2315 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2316 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2318 DataArrayInt *ret2=DataArrayInt::New();
2320 int *ret2Ptr=ret2->getPointer();
2322 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2325 ret2->setName("BoundaryCells");
2330 * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2331 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2332 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2333 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2335 * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2336 * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2337 * equals a cell in \b otherDimM1OnSameCoords.
2339 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2342 * \param [in] otherDimM1OnSameCoords
2343 * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2344 * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2345 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2347 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2349 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2351 checkConnectivityFullyDefined();
2352 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2353 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2357 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2359 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2360 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2361 DataArrayInt *idsOtherInConsti=0;
2362 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2365 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2367 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2368 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2370 s1arr_renum1->sort();
2371 cellIdsRk0=s0arr.retn();
2372 //cellIdsRk1=s_renum1.retn();
2373 cellIdsRk1=s1arr_renum1.retn();
2377 * 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
2378 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2380 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2382 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2389 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2390 revDesc=0; desc=0; descIndx=0;
2391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2393 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2397 * Finds nodes lying on the boundary of \a this mesh.
2398 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2399 * nodes. The caller is to delete this array using decrRef() as it is no
2401 * \throw If the coordinates array is not set.
2402 * \throw If the nodal connectivity of cells is node defined.
2404 * \if ENABLE_EXAMPLES
2405 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2406 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2409 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2411 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2412 return skin->computeFetchedNodeIds();
2415 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2418 return const_cast<MEDCouplingUMesh *>(this);
2422 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2423 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2424 * 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.
2425 * 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.
2426 * 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.
2428 * \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
2429 * parameter is altered during the call.
2430 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2431 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2432 * \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.
2434 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2436 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2437 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2439 typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2441 checkFullyDefined();
2442 otherDimM1OnSameCoords.checkFullyDefined();
2443 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2444 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2445 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2447 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2448 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2449 DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2450 DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2451 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2452 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2453 DAInt s1=m0Part->computeFetchedNodeIds();
2454 DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2455 DAInt s3=s2->buildSubstraction(s1);
2456 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2458 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2459 int nCells2 = m0Part2->getNumberOfCells();
2460 DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2462 // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2463 DataArrayInt *tmp00=0,*tmp11=0;
2464 MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2465 DAInt neighInit00(tmp00);
2466 DAInt neighIInit00(tmp11);
2467 // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2468 DataArrayInt *idsTmp=0;
2469 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2472 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2473 // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2474 // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2475 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2476 DataArrayInt *tmp0=0,*tmp1=0;
2477 // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2478 // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2479 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2480 DAInt neigh00(tmp0);
2481 DAInt neighI00(tmp1);
2483 // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2484 int seed = 0, nIter = 0;
2485 int nIterMax = nCells2+1; // Safety net for the loop
2486 DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2487 hitCells->fillWithValue(-1);
2488 DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2489 cellsToModifyConn0_torenum->alloc(0,1);
2490 while (nIter < nIterMax)
2492 DAInt t = hitCells->getIdsEqual(-1);
2493 if (!t->getNumberOfTuples())
2495 // Connex zone without the crack (to compute the next seed really)
2497 DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2499 for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2500 hitCells->setIJ(*ptr,0,1);
2501 // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2502 DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2503 cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2504 // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2505 DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2506 DAInt nonHitCells = hitCells->getIdsEqual(-1);
2507 DAInt intersec = nonHitCells->buildIntersection(comple);
2508 if (intersec->getNumberOfTuples())
2509 { seed = intersec->getIJ(0,0); }
2514 if (nIter >= nIterMax)
2515 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2517 DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2518 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2519 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2521 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2522 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2523 nodeIdsToDuplicate=s3.retn();
2527 * This method operates a modification of the connectivity and coords in \b this.
2528 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2529 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2530 * 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
2531 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2532 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2534 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2536 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2537 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2539 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2541 int nbOfNodes=getNumberOfNodes();
2542 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2543 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2547 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2548 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2550 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2552 * \sa renumberNodesInConn
2554 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2556 checkConnectivityFullyDefined();
2557 int *conn(getNodalConnectivity()->getPointer());
2558 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2559 int nbOfCells(getNumberOfCells());
2560 for(int i=0;i<nbOfCells;i++)
2561 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2563 int& node=conn[iconn];
2564 if(node>=0)//avoid polyhedron separator
2569 _nodal_connec->declareAsNew();
2574 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2575 * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2578 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2580 checkConnectivityFullyDefined();
2581 int *conn(getNodalConnectivity()->getPointer());
2582 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2583 int nbOfCells(getNumberOfCells());
2584 for(int i=0;i<nbOfCells;i++)
2585 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2587 int& node=conn[iconn];
2588 if(node>=0)//avoid polyhedron separator
2590 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2591 if(it!=newNodeNumbersO2N.end())
2597 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2598 throw INTERP_KERNEL::Exception(oss.str().c_str());
2602 _nodal_connec->declareAsNew();
2607 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2608 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2609 * This method is a generalization of shiftNodeNumbersInConn().
2610 * \warning This method performs no check of validity of new ids. **Use it with care !**
2611 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2612 * this->getNumberOfNodes(), in "Old to New" mode.
2613 * See \ref numbering for more info on renumbering modes.
2614 * \throw If the nodal connectivity of cells is not defined.
2616 * \if ENABLE_EXAMPLES
2617 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2618 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2621 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2623 checkConnectivityFullyDefined();
2624 int *conn=getNodalConnectivity()->getPointer();
2625 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2626 int nbOfCells(getNumberOfCells());
2627 for(int i=0;i<nbOfCells;i++)
2628 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2630 int& node=conn[iconn];
2631 if(node>=0)//avoid polyhedron separator
2633 node=newNodeNumbersO2N[node];
2636 _nodal_connec->declareAsNew();
2641 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2642 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2643 * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2645 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2647 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2649 checkConnectivityFullyDefined();
2650 int *conn=getNodalConnectivity()->getPointer();
2651 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2652 int nbOfCells=getNumberOfCells();
2653 for(int i=0;i<nbOfCells;i++)
2654 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2656 int& node=conn[iconn];
2657 if(node>=0)//avoid polyhedron separator
2662 _nodal_connec->declareAsNew();
2667 * This method operates a modification of the connectivity in \b this.
2668 * 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.
2669 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2670 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2671 * 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
2672 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2673 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2675 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2676 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2678 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2679 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2680 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2682 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2684 checkConnectivityFullyDefined();
2685 std::map<int,int> m;
2687 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2689 int *conn=getNodalConnectivity()->getPointer();
2690 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2691 int nbOfCells=getNumberOfCells();
2692 for(int i=0;i<nbOfCells;i++)
2693 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2695 int& node=conn[iconn];
2696 if(node>=0)//avoid polyhedron separator
2698 std::map<int,int>::iterator it=m.find(node);
2707 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2709 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2710 * After the call of this method the number of cells remains the same as before.
2712 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2713 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2714 * be strictly in [0;this->getNumberOfCells()).
2716 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2717 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2718 * should be contained in[0;this->getNumberOfCells()).
2720 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2723 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2725 checkConnectivityFullyDefined();
2726 int nbCells=getNumberOfCells();
2727 const int *array=old2NewBg;
2729 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2731 const int *conn=_nodal_connec->getConstPointer();
2732 const int *connI=_nodal_connec_index->getConstPointer();
2733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2735 const int *n2oPtr=n2o->begin();
2736 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2737 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2738 newConn->copyStringInfoFrom(*_nodal_connec);
2739 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2740 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2741 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2743 int *newC=newConn->getPointer();
2744 int *newCI=newConnI->getPointer();
2747 for(int i=0;i<nbCells;i++)
2750 int nbOfElts=connI[pos+1]-connI[pos];
2751 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2756 setConnectivity(newConn,newConnI);
2758 free(const_cast<int *>(array));
2762 * Finds cells whose bounding boxes intersect a given bounding box.
2763 * \param [in] bbox - an array defining the bounding box via coordinates of its
2764 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2766 * \param [in] eps - a factor used to increase size of the bounding box of cell
2767 * before comparing it with \a bbox. This factor is multiplied by the maximal
2768 * extent of the bounding box of cell to produce an addition to this bounding box.
2769 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2770 * cells. The caller is to delete this array using decrRef() as it is no more
2772 * \throw If the coordinates array is not set.
2773 * \throw If the nodal connectivity of cells is not defined.
2775 * \if ENABLE_EXAMPLES
2776 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2777 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2780 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2782 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2783 if(getMeshDimension()==-1)
2785 elems->pushBackSilent(0);
2786 return elems.retn();
2788 int dim=getSpaceDimension();
2789 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2790 const int* conn = getNodalConnectivity()->getConstPointer();
2791 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2792 const double* coords = getCoords()->getConstPointer();
2793 int nbOfCells=getNumberOfCells();
2794 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2796 for (int i=0; i<dim; i++)
2798 elem_bb[i*2]=std::numeric_limits<double>::max();
2799 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2802 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2804 int node= conn[inode];
2805 if(node>=0)//avoid polyhedron separator
2807 for (int idim=0; idim<dim; idim++)
2809 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2811 elem_bb[idim*2] = coords[node*dim+idim] ;
2813 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2815 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2820 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2821 elems->pushBackSilent(ielem);
2823 return elems.retn();
2827 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2828 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2829 * added in 'elems' parameter.
2831 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2834 if(getMeshDimension()==-1)
2836 elems->pushBackSilent(0);
2837 return elems.retn();
2839 int dim=getSpaceDimension();
2840 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2841 const int* conn = getNodalConnectivity()->getConstPointer();
2842 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2843 const double* coords = getCoords()->getConstPointer();
2844 int nbOfCells=getNumberOfCells();
2845 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2847 for (int i=0; i<dim; i++)
2849 elem_bb[i*2]=std::numeric_limits<double>::max();
2850 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2853 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2855 int node= conn[inode];
2856 if(node>=0)//avoid polyhedron separator
2858 for (int idim=0; idim<dim; idim++)
2860 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2862 elem_bb[idim*2] = coords[node*dim+idim] ;
2864 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2866 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2871 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2872 elems->pushBackSilent(ielem);
2874 return elems.retn();
2878 * Returns a type of a cell by its id.
2879 * \param [in] cellId - the id of the cell of interest.
2880 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2881 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2883 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2885 const int *ptI=_nodal_connec_index->getConstPointer();
2886 const int *pt=_nodal_connec->getConstPointer();
2887 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2888 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2891 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2892 throw INTERP_KERNEL::Exception(oss.str().c_str());
2897 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2898 * This method does not throw exception if geometric type \a type is not in \a this.
2899 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2900 * The coordinates array is not considered here.
2902 * \param [in] type the geometric type
2903 * \return cell ids in this having geometric type \a type.
2905 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2910 checkConnectivityFullyDefined();
2911 int nbCells=getNumberOfCells();
2912 int mdim=getMeshDimension();
2913 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2914 if(mdim!=(int)cm.getDimension())
2915 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2916 const int *ptI=_nodal_connec_index->getConstPointer();
2917 const int *pt=_nodal_connec->getConstPointer();
2918 for(int i=0;i<nbCells;i++)
2920 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2921 ret->pushBackSilent(i);
2927 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2929 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2931 const int *ptI=_nodal_connec_index->getConstPointer();
2932 const int *pt=_nodal_connec->getConstPointer();
2933 int nbOfCells=getNumberOfCells();
2935 for(int i=0;i<nbOfCells;i++)
2936 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2942 * Returns the nodal connectivity of a given cell.
2943 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2944 * all returned node ids can be used in getCoordinatesOfNode().
2945 * \param [in] cellId - an id of the cell of interest.
2946 * \param [in,out] conn - a vector where the node ids are appended. It is not
2947 * cleared before the appending.
2948 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2950 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2952 const int *ptI=_nodal_connec_index->getConstPointer();
2953 const int *pt=_nodal_connec->getConstPointer();
2954 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2959 std::string MEDCouplingUMesh::simpleRepr() const
2961 static const char msg0[]="No coordinates specified !";
2962 std::ostringstream ret;
2963 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2964 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2966 double tt=getTime(tmpp1,tmpp2);
2967 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2968 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2970 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2972 { ret << " Mesh dimension has not been set or is invalid !"; }
2975 const int spaceDim=getSpaceDimension();
2976 ret << spaceDim << "\nInfo attached on space dimension : ";
2977 for(int i=0;i<spaceDim;i++)
2978 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2982 ret << msg0 << "\n";
2983 ret << "Number of nodes : ";
2985 ret << getNumberOfNodes() << "\n";
2987 ret << msg0 << "\n";
2988 ret << "Number of cells : ";
2989 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2990 ret << getNumberOfCells() << "\n";
2992 ret << "No connectivity specified !" << "\n";
2993 ret << "Cell types present : ";
2994 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2996 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2997 ret << cm.getRepr() << " ";
3003 std::string MEDCouplingUMesh::advancedRepr() const
3005 std::ostringstream ret;
3006 ret << simpleRepr();
3007 ret << "\nCoordinates array : \n___________________\n\n";
3009 _coords->reprWithoutNameStream(ret);
3011 ret << "No array set !\n";
3012 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3013 reprConnectivityOfThisLL(ret);
3018 * This method returns a C++ code that is a dump of \a this.
3019 * This method will throw if this is not fully defined.
3021 std::string MEDCouplingUMesh::cppRepr() const
3023 static const char coordsName[]="coords";
3024 static const char connName[]="conn";
3025 static const char connIName[]="connI";
3026 checkFullyDefined();
3027 std::ostringstream ret; ret << "// coordinates" << std::endl;
3028 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3029 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3030 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3031 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3032 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3033 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3034 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3038 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3040 std::ostringstream ret;
3041 reprConnectivityOfThisLL(ret);
3046 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3047 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3048 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3051 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3052 * 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
3053 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3055 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3057 int mdim=getMeshDimension();
3059 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3060 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3062 bool needToCpyCT=true;
3065 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3073 if(!_nodal_connec_index)
3075 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3080 tmp2=_nodal_connec_index;
3083 ret->setConnectivity(tmp1,tmp2,false);
3088 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3089 ret->setCoords(coords);
3092 ret->setCoords(_coords);
3096 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3098 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3100 int nbOfCells=getNumberOfCells();
3101 const int *c=_nodal_connec->getConstPointer();
3102 const int *ci=_nodal_connec_index->getConstPointer();
3103 for(int i=0;i<nbOfCells;i++)
3105 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3106 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3107 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3112 stream << "Connectivity not defined !\n";
3115 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3117 const int *ptI=_nodal_connec_index->getConstPointer();
3118 const int *pt=_nodal_connec->getConstPointer();
3119 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3120 return ptI[cellId+1]-ptI[cellId]-1;
3122 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3126 * Returns types of cells of the specified part of \a this mesh.
3127 * This method avoids computing sub-mesh explicitely to get its types.
3128 * \param [in] begin - an array of cell ids of interest.
3129 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3130 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3131 * describing the cell types.
3132 * \throw If the coordinates array is not set.
3133 * \throw If the nodal connectivity of cells is not defined.
3134 * \sa getAllGeoTypes()
3136 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3138 checkFullyDefined();
3139 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3140 const int *conn=_nodal_connec->getConstPointer();
3141 const int *connIndex=_nodal_connec_index->getConstPointer();
3142 for(const int *w=begin;w!=end;w++)
3143 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3148 * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3149 * Optionally updates
3150 * a set of types of cells constituting \a this mesh.
3151 * This method is for advanced users having prepared their connectivity before. For
3152 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3153 * \param [in] conn - the nodal connectivity array.
3154 * \param [in] connIndex - the nodal connectivity index array.
3155 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3158 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3160 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3161 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3162 if(isComputingTypes)
3168 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3169 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3171 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3172 _nodal_connec(0),_nodal_connec_index(0),
3173 _types(other._types)
3175 if(other._nodal_connec)
3176 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3177 if(other._nodal_connec_index)
3178 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3181 MEDCouplingUMesh::~MEDCouplingUMesh()
3184 _nodal_connec->decrRef();
3185 if(_nodal_connec_index)
3186 _nodal_connec_index->decrRef();
3190 * Recomputes a set of cell types of \a this mesh. For more info see
3191 * \ref MEDCouplingUMeshNodalConnectivity.
3193 void MEDCouplingUMesh::computeTypes()
3195 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3199 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3201 void MEDCouplingUMesh::checkFullyDefined() const
3203 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3204 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3208 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3210 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3212 if(!_nodal_connec_index || !_nodal_connec)
3213 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3217 * Returns a number of cells constituting \a this mesh.
3218 * \return int - the number of cells in \a this mesh.
3219 * \throw If the nodal connectivity of cells is not defined.
3221 int MEDCouplingUMesh::getNumberOfCells() const
3223 if(_nodal_connec_index)
3224 return _nodal_connec_index->getNumberOfTuples()-1;
3229 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3233 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3234 * mesh. For more info see \ref meshes.
3235 * \return int - the dimension of \a this mesh.
3236 * \throw If the mesh dimension is not defined using setMeshDimension().
3238 int MEDCouplingUMesh::getMeshDimension() const
3241 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3246 * Returns a length of the nodal connectivity array.
3247 * This method is for test reason. Normally the integer returned is not useable by
3248 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3249 * \return int - the length of the nodal connectivity array.
3251 int MEDCouplingUMesh::getMeshLength() const
3253 return _nodal_connec->getNbOfElems();
3257 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3259 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3261 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3262 tinyInfo.push_back(getMeshDimension());
3263 tinyInfo.push_back(getNumberOfCells());
3265 tinyInfo.push_back(getMeshLength());
3267 tinyInfo.push_back(-1);
3271 * First step of unserialization process.
3273 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3275 return tinyInfo[6]<=0;
3279 * Second step of serialization process.
3280 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3283 * \param littleStrings
3285 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3287 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3289 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3293 * Third and final step of serialization process.
3295 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3297 MEDCouplingPointSet::serialize(a1,a2);
3298 if(getMeshDimension()>-1)
3300 a1=DataArrayInt::New();
3301 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3302 int *ptA1=a1->getPointer();
3303 const int *conn=getNodalConnectivity()->getConstPointer();
3304 const int *index=getNodalConnectivityIndex()->getConstPointer();
3305 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3306 std::copy(conn,conn+getMeshLength(),ptA1);
3313 * Second and final unserialization process.
3314 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3316 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3318 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3319 setMeshDimension(tinyInfo[5]);
3323 const int *recvBuffer=a1->getConstPointer();
3324 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3325 myConnecIndex->alloc(tinyInfo[6]+1,1);
3326 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3328 myConnec->alloc(tinyInfo[7],1);
3329 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3330 setConnectivity(myConnec, myConnecIndex);
3335 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3336 * CellIds are given using range specified by a start an end and step.
3338 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3340 checkFullyDefined();
3341 int ncell=getNumberOfCells();
3342 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3343 ret->_mesh_dim=_mesh_dim;
3344 ret->setCoords(_coords);
3345 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3347 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3349 const int *conn=_nodal_connec->getConstPointer();
3350 const int *connIndex=_nodal_connec_index->getConstPointer();
3351 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3353 if(work>=0 && work<ncell)
3355 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3359 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3360 throw INTERP_KERNEL::Exception(oss.str().c_str());
3363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3364 int *newConnPtr=newConn->getPointer();
3365 std::set<INTERP_KERNEL::NormalizedCellType> types;
3367 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3369 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3370 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3372 ret->setConnectivity(newConn,newConnI,false);
3374 ret->copyTinyInfoFrom(this);
3379 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3380 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3381 * The return newly allocated mesh will share the same coordinates as \a this.
3383 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3385 checkConnectivityFullyDefined();
3386 int ncell=getNumberOfCells();
3387 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3388 ret->_mesh_dim=_mesh_dim;
3389 ret->setCoords(_coords);
3390 std::size_t nbOfElemsRet=std::distance(begin,end);
3391 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3393 const int *conn=_nodal_connec->getConstPointer();
3394 const int *connIndex=_nodal_connec_index->getConstPointer();
3396 for(const int *work=begin;work!=end;work++,newNbring++)
3398 if(*work>=0 && *work<ncell)
3399 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3403 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3404 throw INTERP_KERNEL::Exception(oss.str().c_str());
3407 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3408 int *connRetWork=connRet;
3409 std::set<INTERP_KERNEL::NormalizedCellType> types;
3410 for(const int *work=begin;work!=end;work++)
3412 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3413 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3415 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3416 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3418 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3419 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3421 ret->copyTinyInfoFrom(this);
3426 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3428 * For 1D cells, the returned field contains lengths.<br>
3429 * For 2D cells, the returned field contains areas.<br>
3430 * For 3D cells, the returned field contains volumes.
3431 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3432 * orientation, i.e. the volume is always positive.
3433 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3434 * and one time . The caller is to delete this field using decrRef() as it is no
3437 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3439 std::string name="MeasureOfMesh_";
3441 int nbelem=getNumberOfCells();
3442 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3443 field->setName(name);
3444 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3445 array->alloc(nbelem,1);
3446 double *area_vol=array->getPointer();
3447 field->setArray(array) ; array=0;
3448 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3449 field->synchronizeTimeWithMesh();
3450 if(getMeshDimension()!=-1)
3453 INTERP_KERNEL::NormalizedCellType type;
3454 int dim_space=getSpaceDimension();
3455 const double *coords=getCoords()->getConstPointer();
3456 const int *connec=getNodalConnectivity()->getConstPointer();
3457 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3458 for(int iel=0;iel<nbelem;iel++)
3460 ipt=connec_index[iel];
3461 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3462 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);
3465 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3469 area_vol[0]=std::numeric_limits<double>::max();
3471 return field.retn();
3475 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3477 * For 1D cells, the returned array contains lengths.<br>
3478 * For 2D cells, the returned array contains areas.<br>
3479 * For 3D cells, the returned array contains volumes.
3480 * This method avoids building explicitly a part of \a this mesh to perform the work.
3481 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3482 * orientation, i.e. the volume is always positive.
3483 * \param [in] begin - an array of cell ids of interest.
3484 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3485 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3486 * delete this array using decrRef() as it is no more needed.
3488 * \if ENABLE_EXAMPLES
3489 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3490 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3492 * \sa getMeasureField()
3494 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3496 std::string name="PartMeasureOfMesh_";
3498 int nbelem=(int)std::distance(begin,end);
3499 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3500 array->setName(name);
3501 array->alloc(nbelem,1);
3502 double *area_vol=array->getPointer();
3503 if(getMeshDimension()!=-1)
3506 INTERP_KERNEL::NormalizedCellType type;
3507 int dim_space=getSpaceDimension();
3508 const double *coords=getCoords()->getConstPointer();
3509 const int *connec=getNodalConnectivity()->getConstPointer();
3510 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3511 for(const int *iel=begin;iel!=end;iel++)
3513 ipt=connec_index[*iel];
3514 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3515 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3518 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3522 area_vol[0]=std::numeric_limits<double>::max();
3524 return array.retn();
3528 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3529 * \a this one. The returned field contains the dual cell volume for each corresponding
3530 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3531 * the dual mesh in P1 sens of \a this.<br>
3532 * For 1D cells, the returned field contains lengths.<br>
3533 * For 2D cells, the returned field contains areas.<br>
3534 * For 3D cells, the returned field contains volumes.
3535 * This method is useful to check "P1*" conservative interpolators.
3536 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3537 * orientation, i.e. the volume is always positive.
3538 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3539 * nodes and one time. The caller is to delete this array using decrRef() as
3540 * it is no more needed.
3542 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3544 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3545 std::string name="MeasureOnNodeOfMesh_";
3547 int nbNodes=getNumberOfNodes();
3548 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3549 double cst=1./((double)getMeshDimension()+1.);
3550 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3551 array->alloc(nbNodes,1);
3552 double *valsToFill=array->getPointer();
3553 std::fill(valsToFill,valsToFill+nbNodes,0.);
3554 const double *values=tmp->getArray()->getConstPointer();
3555 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3556 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3557 getReverseNodalConnectivity(da,daInd);
3558 const int *daPtr=da->getConstPointer();
3559 const int *daIPtr=daInd->getConstPointer();
3560 for(int i=0;i<nbNodes;i++)
3561 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3562 valsToFill[i]+=cst*values[*cell];
3564 ret->setArray(array);
3569 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3570 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3571 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3572 * and are normalized.
3573 * <br> \a this can be either
3574 * - a 2D mesh in 2D or 3D space or
3575 * - an 1D mesh in 2D space.
3577 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3578 * cells and one time. The caller is to delete this field using decrRef() as
3579 * it is no more needed.
3580 * \throw If the nodal connectivity of cells is not defined.
3581 * \throw If the coordinates array is not set.
3582 * \throw If the mesh dimension is not set.
3583 * \throw If the mesh and space dimension is not as specified above.
3585 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3587 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3588 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3589 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3590 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3591 int nbOfCells=getNumberOfCells();
3592 int nbComp=getMeshDimension()+1;
3593 array->alloc(nbOfCells,nbComp);
3594 double *vals=array->getPointer();
3595 const int *connI=_nodal_connec_index->getConstPointer();
3596 const int *conn=_nodal_connec->getConstPointer();
3597 const double *coords=_coords->getConstPointer();
3598 if(getMeshDimension()==2)
3600 if(getSpaceDimension()==3)
3602 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3603 const double *locPtr=loc->getConstPointer();
3604 for(int i=0;i<nbOfCells;i++,vals+=3)
3606 int offset=connI[i];
3607 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3608 double n=INTERP_KERNEL::norm<3>(vals);
3609 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3614 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3615 const double *isAbsPtr=isAbs->getArray()->begin();
3616 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3617 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3620 else//meshdimension==1
3623 for(int i=0;i<nbOfCells;i++)
3625 int offset=connI[i];
3626 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3627 double n=INTERP_KERNEL::norm<2>(tmp);
3628 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3633 ret->setArray(array);
3635 ret->synchronizeTimeWithSupport();
3640 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3641 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3642 * and are normalized.
3643 * <br> \a this can be either
3644 * - a 2D mesh in 2D or 3D space or
3645 * - an 1D mesh in 2D space.
3647 * This method avoids building explicitly a part of \a this mesh to perform the work.
3648 * \param [in] begin - an array of cell ids of interest.
3649 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3650 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3651 * cells and one time. The caller is to delete this field using decrRef() as
3652 * it is no more needed.
3653 * \throw If the nodal connectivity of cells is not defined.
3654 * \throw If the coordinates array is not set.
3655 * \throw If the mesh dimension is not set.
3656 * \throw If the mesh and space dimension is not as specified above.
3657 * \sa buildOrthogonalField()
3659 * \if ENABLE_EXAMPLES
3660 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3661 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3664 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3666 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3667 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3668 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3669 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3670 std::size_t nbelems=std::distance(begin,end);
3671 int nbComp=getMeshDimension()+1;
3672 array->alloc((int)nbelems,nbComp);
3673 double *vals=array->getPointer();
3674 const int *connI=_nodal_connec_index->getConstPointer();
3675 const int *conn=_nodal_connec->getConstPointer();
3676 const double *coords=_coords->getConstPointer();
3677 if(getMeshDimension()==2)
3679 if(getSpaceDimension()==3)
3681 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3682 const double *locPtr=loc->getConstPointer();
3683 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3685 int offset=connI[*i];
3686 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3687 double n=INTERP_KERNEL::norm<3>(vals);
3688 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3693 for(std::size_t i=0;i<nbelems;i++)
3694 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3697 else//meshdimension==1
3700 for(const int *i=begin;i!=end;i++)
3702 int offset=connI[*i];
3703 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3704 double n=INTERP_KERNEL::norm<2>(tmp);
3705 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3710 ret->setArray(array);
3712 ret->synchronizeTimeWithSupport();
3717 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3718 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3719 * and are \b not normalized.
3720 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3721 * cells and one time. The caller is to delete this field using decrRef() as
3722 * it is no more needed.
3723 * \throw If the nodal connectivity of cells is not defined.
3724 * \throw If the coordinates array is not set.
3725 * \throw If \a this->getMeshDimension() != 1.
3726 * \throw If \a this mesh includes cells of type other than SEG2.
3728 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3730 if(getMeshDimension()!=1)
3731 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3732 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3733 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3734 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3735 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3736 int nbOfCells=getNumberOfCells();
3737 int spaceDim=getSpaceDimension();
3738 array->alloc(nbOfCells,spaceDim);
3739 double *pt=array->getPointer();
3740 const double *coo=getCoords()->getConstPointer();
3741 std::vector<int> conn;
3743 for(int i=0;i<nbOfCells;i++)
3746 getNodeIdsOfCell(i,conn);
3747 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3749 ret->setArray(array);
3751 ret->synchronizeTimeWithSupport();
3756 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3757 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3758 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3759 * from. If a result face is shared by two 3D cells, then the face in included twice in
3761 * \param [in] origin - 3 components of a point defining location of the plane.
3762 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3763 * must be greater than 1e-6.
3764 * \param [in] eps - half-thickness of the plane.
3765 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3766 * producing correspondent 2D cells. The caller is to delete this array
3767 * using decrRef() as it is no more needed.
3768 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3769 * not share the node coordinates array with \a this mesh. The caller is to
3770 * delete this mesh using decrRef() as it is no more needed.
3771 * \throw If the coordinates array is not set.
3772 * \throw If the nodal connectivity of cells is not defined.
3773 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3774 * \throw If magnitude of \a vec is less than 1e-6.
3775 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3776 * \throw If \a this includes quadratic cells.
3778 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3780 checkFullyDefined();
3781 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3784 if(candidates->empty())
3785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3786 std::vector<int> nodes;
3787 DataArrayInt *cellIds1D=0;
3788 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3789 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3791 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3794 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3795 revDesc2=0; revDescIndx2=0;
3796 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3797 revDesc1=0; revDescIndx1=0;
3798 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3801 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3802 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3804 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3805 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3806 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3807 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3808 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3810 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3811 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3812 if(cellIds2->empty())
3813 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3814 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3815 ret->setCoords(mDesc1->getCoords());
3816 ret->setConnectivity(conn,connI,true);
3817 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3822 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3823 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
3824 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3826 * \param [in] origin - 3 components of a point defining location of the plane.
3827 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3828 * must be greater than 1e-6.
3829 * \param [in] eps - half-thickness of the plane.
3830 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3831 * producing correspondent segments. The caller is to delete this array
3832 * using decrRef() as it is no more needed.
3833 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3834 * mesh in 3D space. This mesh does not share the node coordinates array with
3835 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3837 * \throw If the coordinates array is not set.
3838 * \throw If the nodal connectivity of cells is not defined.
3839 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3840 * \throw If magnitude of \a vec is less than 1e-6.
3841 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3842 * \throw If \a this includes quadratic cells.
3844 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3846 checkFullyDefined();
3847 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3850 if(candidates->empty())
3851 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3852 std::vector<int> nodes;
3853 DataArrayInt *cellIds1D=0;
3854 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3855 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3858 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3860 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3861 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3864 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3865 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3867 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3868 int ncellsSub=subMesh->getNumberOfCells();
3869 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3870 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3871 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3872 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3875 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3876 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3877 for(int i=0;i<ncellsSub;i++)
3879 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3881 if(cut3DSurf[i].first!=-2)
3883 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3884 connI->pushBackSilent(conn->getNumberOfTuples());
3885 cellIds2->pushBackSilent(i);
3889 int cellId3DSurf=cut3DSurf[i].second;
3890 int offset=nodalI[cellId3DSurf]+1;
3891 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3892 for(int j=0;j<nbOfEdges;j++)
3894 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3895 connI->pushBackSilent(conn->getNumberOfTuples());
3896 cellIds2->pushBackSilent(cellId3DSurf);
3901 if(cellIds2->empty())
3902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3903 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3904 ret->setCoords(mDesc1->getCoords());
3905 ret->setConnectivity(conn,connI,true);
3906 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3911 * Finds cells whose bounding boxes intersect a given plane.
3912 * \param [in] origin - 3 components of a point defining location of the plane.
3913 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3914 * must be greater than 1e-6.
3915 * \param [in] eps - half-thickness of the plane.
3916 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3917 * cells. The caller is to delete this array using decrRef() as it is no more
3919 * \throw If the coordinates array is not set.
3920 * \throw If the nodal connectivity of cells is not defined.
3921 * \throw If \a this->getSpaceDimension() != 3.
3922 * \throw If magnitude of \a vec is less than 1e-6.
3923 * \sa buildSlice3D()
3925 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3927 checkFullyDefined();
3928 if(getSpaceDimension()!=3)
3929 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3930 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3934 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3935 double angle=acos(vec[2]/normm);
3936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3940 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3941 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3942 if(normm2/normm>1e-6)
3943 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3944 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3946 mw->getBoundingBox(bbox);
3947 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3948 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3952 getBoundingBox(bbox);
3953 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3954 cellIds=getCellsInBoundingBox(bbox,eps);
3956 return cellIds.retn();
3960 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3961 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3962 * No consideration of coordinate is done by this method.
3963 * 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)
3964 * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3966 bool MEDCouplingUMesh::isContiguous1D() const
3968 if(getMeshDimension()!=1)
3969 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3970 int nbCells=getNumberOfCells();
3972 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3973 const int *connI=_nodal_connec_index->getConstPointer();
3974 const int *conn=_nodal_connec->getConstPointer();
3975 int ref=conn[connI[0]+2];
3976 for(int i=1;i<nbCells;i++)
3978 if(conn[connI[i]+1]!=ref)
3980 ref=conn[connI[i]+2];
3986 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3987 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3988 * \param pt reference point of the line
3989 * \param v normalized director vector of the line
3990 * \param eps max precision before throwing an exception
3991 * \param res output of size this->getNumberOfCells
3993 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3995 if(getMeshDimension()!=1)
3996 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3997 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3998 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3999 if(getSpaceDimension()!=3)
4000 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4001 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4002 const double *fPtr=f->getArray()->getConstPointer();
4004 for(int i=0;i<getNumberOfCells();i++)
4006 const double *tmp1=fPtr+3*i;
4007 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4008 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4009 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4010 double n1=INTERP_KERNEL::norm<3>(tmp);
4011 n1/=INTERP_KERNEL::norm<3>(tmp1);
4013 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4015 const double *coo=getCoords()->getConstPointer();
4016 for(int i=0;i<getNumberOfNodes();i++)
4018 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4019 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4020 res[i]=std::accumulate(tmp,tmp+3,0.);
4025 * 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.
4026 * \a this is expected to be a mesh so that its space dimension is equal to its
4027 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4028 * 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).
4030 * 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
4031 * 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).
4032 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4034 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4035 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4037 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4038 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4039 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4040 * \return the positive value of the distance.
4041 * \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
4043 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4045 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4047 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4048 if(meshDim!=spaceDim-1)
4049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4050 if(meshDim!=2 && meshDim!=1)
4051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4052 checkFullyDefined();
4053 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4054 { 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()); }
4055 DataArrayInt *ret1=0;
4056 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4057 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4059 cellId=*ret1Safe->begin();
4060 return *ret0->begin();
4064 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4065 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4066 * 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
4067 * 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).
4068 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4070 * \a this is expected to be a mesh so that its space dimension is equal to its
4071 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4072 * 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).
4074 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4075 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4077 * \param [in] pts the list of points in which each tuple represents a point
4078 * \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.
4079 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4080 * \throw if number of components of \a pts is not equal to the space dimension.
4081 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4082 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4084 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4087 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4088 pts->checkAllocated();
4089 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4090 if(meshDim!=spaceDim-1)
4091 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4092 if(meshDim!=2 && meshDim!=1)
4093 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4094 if(pts->getNumberOfComponents()!=spaceDim)
4096 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4097 throw INTERP_KERNEL::Exception(oss.str().c_str());
4099 checkFullyDefined();
4100 int nbCells=getNumberOfCells();
4102 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4103 int nbOfPts=pts->getNumberOfTuples();
4104 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4106 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4107 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4108 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4109 const double *bbox(bboxArr->begin());
4114 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4115 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4117 double x=std::numeric_limits<double>::max();
4118 std::vector<int> elems;
4119 myTree.getMinDistanceOfMax(ptsPtr,x);
4120 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4121 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4127 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4128 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4130 double x=std::numeric_limits<double>::max();
4131 std::vector<int> elems;
4132 myTree.getMinDistanceOfMax(ptsPtr,x);
4133 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4134 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4139 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4141 cellIds=ret1.retn();
4148 * \param [in] pt the start pointer (included) of the coordinates of the point
4149 * \param [in] cellIdsBg the start pointer (included) of cellIds
4150 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4151 * \param [in] nc nodal connectivity
4152 * \param [in] ncI nodal connectivity index
4153 * \param [in,out] ret0 the min distance between \a this and the external input point
4154 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4155 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4157 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)
4160 ret0=std::numeric_limits<double>::max();
4161 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4163 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4165 case INTERP_KERNEL::NORM_TRI3:
4167 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4169 { ret0=tmp; cellId=*zeCell; }
4172 case INTERP_KERNEL::NORM_QUAD4:
4173 case INTERP_KERNEL::NORM_POLYGON:
4175 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4177 { ret0=tmp; cellId=*zeCell; }
4181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4187 * \param [in] pt the start pointer (included) of the coordinates of the point
4188 * \param [in] cellIdsBg the start pointer (included) of cellIds
4189 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4190 * \param [in] nc nodal connectivity
4191 * \param [in] ncI nodal connectivity index
4192 * \param [in,out] ret0 the min distance between \a this and the external input point
4193 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4194 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4196 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)
4199 ret0=std::numeric_limits<double>::max();
4200 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4202 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4204 case INTERP_KERNEL::NORM_SEG2:
4206 std::size_t uselessEntry=0;
4207 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4210 { ret0=tmp; cellId=*zeCell; }
4214 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4221 * Finds cells in contact with a ball (i.e. a point with precision).
4222 * 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.
4223 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4225 * \warning This method is suitable if the caller intends to evaluate only one
4226 * point, for more points getCellsContainingPoints() is recommended as it is
4228 * \param [in] pos - array of coordinates of the ball central point.
4229 * \param [in] eps - ball radius.
4230 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4231 * if there are no such cells.
4232 * \throw If the coordinates array is not set.
4233 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4235 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4237 std::vector<int> elts;
4238 getCellsContainingPoint(pos,eps,elts);
4241 return elts.front();
4245 * Finds cells in contact with a ball (i.e. a point with precision).
4246 * 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.
4247 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4248 * \warning This method is suitable if the caller intends to evaluate only one
4249 * point, for more points getCellsContainingPoints() is recommended as it is
4251 * \param [in] pos - array of coordinates of the ball central point.
4252 * \param [in] eps - ball radius.
4253 * \param [out] elts - vector returning ids of the found cells. It is cleared
4254 * before inserting ids.
4255 * \throw If the coordinates array is not set.
4256 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4258 * \if ENABLE_EXAMPLES
4259 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4260 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4263 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4266 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4267 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4272 namespace MEDCoupling
4274 template<const int SPACEDIMM>
4278 static const int MY_SPACEDIM=SPACEDIMM;
4279 static const int MY_MESHDIM=8;
4280 typedef int MyConnType;
4281 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4283 // useless, but for windows compilation ...
4284 const double* getCoordinatesPtr() const { return 0; }
4285 const int* getConnectivityPtr() const { return 0; }
4286 const int* getConnectivityIndexPtr() const { return 0; }
4287 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4291 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4293 INTERP_KERNEL::Edge *ret(0);
4294 MEDCouplingAutoRefCountObjectPtr<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]));
4295 m[n0]=bg[0]; m[n1]=bg[1];
4298 case INTERP_KERNEL::NORM_SEG2:
4300 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4303 case INTERP_KERNEL::NORM_SEG3:
4305 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4306 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4307 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4308 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4309 bool colinearity(inters.areColinears());
4310 delete e1; delete e2;
4312 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4314 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4318 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4323 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4325 INTERP_KERNEL::Edge *ret=0;
4328 case INTERP_KERNEL::NORM_SEG2:
4330 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4333 case INTERP_KERNEL::NORM_SEG3:
4335 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4336 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4337 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4338 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4339 bool colinearity=inters.areColinears();
4340 delete e1; delete e2;
4342 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4344 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4345 mapp2[bg[2]].second=false;
4349 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4355 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4356 * the global mesh 'mDesc'.
4357 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4358 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4360 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4361 std::map<INTERP_KERNEL::Node *,int>& mapp)
4364 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.
4365 const double *coo=mDesc->getCoords()->getConstPointer();
4366 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4367 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4369 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4370 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4371 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4373 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4374 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4376 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4377 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4379 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4380 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4382 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4384 if((*it2).second.second)
4385 mapp[(*it2).second.first]=(*it2).first;
4386 ((*it2).second.first)->decrRef();
4391 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4395 int locId=nodeId-offset2;
4396 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4400 int locId=nodeId-offset1;
4401 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4403 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4407 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4409 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4410 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4411 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4413 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4415 int eltId1=abs(*desc1)-1;
4416 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4418 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4419 if(it==mappRev.end())
4421 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4432 template<int SPACEDIM>
4433 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4434 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4436 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4437 int *eltsIndexPtr(eltsIndex->getPointer());
4438 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4439 const double *bbox(bboxArr->begin());
4440 int nbOfCells=getNumberOfCells();
4441 const int *conn=_nodal_connec->getConstPointer();
4442 const int *connI=_nodal_connec_index->getConstPointer();
4443 double bb[2*SPACEDIM];
4444 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4445 for(int i=0;i<nbOfPoints;i++)
4447 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4448 for(int j=0;j<SPACEDIM;j++)
4450 bb[2*j]=pos[SPACEDIM*i+j];
4451 bb[2*j+1]=pos[SPACEDIM*i+j];
4453 std::vector<int> candidates;
4454 myTree.getIntersectingElems(bb,candidates);
4455 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4457 int sz(connI[(*iter)+1]-connI[*iter]-1);
4458 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4460 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4461 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4465 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4466 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4467 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4468 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4469 INTERP_KERNEL::QuadraticPolygon *pol(0);
4470 for(int j=0;j<sz;j++)
4472 int nodeId(conn[connI[*iter]+1+j]);
4473 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4475 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4476 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4478 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4479 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4480 double a(0.),b(0.),c(0.);
4481 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4482 status=pol->isInOrOut2(n);
4483 delete pol; n->decrRef();
4487 eltsIndexPtr[i+1]++;
4488 elts->pushBackSilent(*iter);
4494 * Finds cells in contact with several balls (i.e. points with precision).
4495 * This method is an extension of getCellContainingPoint() and
4496 * getCellsContainingPoint() for the case of multiple points.
4497 * 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.
4498 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4499 * \param [in] pos - an array of coordinates of points in full interlace mode :
4500 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4501 * this->getSpaceDimension() * \a nbOfPoints
4502 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4503 * \param [in] eps - radius of balls (i.e. the precision).
4504 * \param [out] elts - vector returning ids of found cells.
4505 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4506 * dividing cell ids in \a elts into groups each referring to one
4507 * point. Its every element (except the last one) is an index pointing to the
4508 * first id of a group of cells. For example cells in contact with the *i*-th
4509 * point are described by following range of indices:
4510 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4511 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4512 * Number of cells in contact with the *i*-th point is
4513 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4514 * \throw If the coordinates array is not set.
4515 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4517 * \if ENABLE_EXAMPLES
4518 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4519 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4522 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4525 int spaceDim=getSpaceDimension();
4526 int mDim=getMeshDimension();
4531 const double *coords=_coords->getConstPointer();
4532 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4539 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4541 else if(spaceDim==2)
4545 const double *coords=_coords->getConstPointer();
4546 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4549 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4551 else if(spaceDim==1)
4555 const double *coords=_coords->getConstPointer();
4556 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4559 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4562 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4566 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4567 * least two its edges intersect each other anywhere except their extremities. An
4568 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4569 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4570 * cleared before filling in.
4571 * \param [in] eps - precision.
4572 * \throw If \a this->getMeshDimension() != 2.
4573 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4575 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4577 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4578 if(getMeshDimension()!=2)
4579 throw INTERP_KERNEL::Exception(msg);
4580 int spaceDim=getSpaceDimension();
4581 if(spaceDim!=2 && spaceDim!=3)
4582 throw INTERP_KERNEL::Exception(msg);
4583 const int *conn=_nodal_connec->getConstPointer();
4584 const int *connI=_nodal_connec_index->getConstPointer();
4585 int nbOfCells=getNumberOfCells();
4586 std::vector<double> cell2DinS2;
4587 for(int i=0;i<nbOfCells;i++)
4589 int offset=connI[i];
4590 int nbOfNodesForCell=connI[i+1]-offset-1;
4591 if(nbOfNodesForCell<=3)
4593 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4594 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4595 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4602 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4604 * 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.
4605 * 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.
4607 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4608 * This convex envelop is computed using Jarvis march algorithm.
4609 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4610 * 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)
4611 * 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.
4613 * \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.
4614 * \sa MEDCouplingUMesh::colinearize2D
4616 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4618 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4619 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4620 checkFullyDefined();
4621 const double *coords=getCoords()->getConstPointer();
4622 int nbOfCells=getNumberOfCells();
4623 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4624 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4625 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4626 int *workIndexOut=nodalConnecIndexOut->getPointer();
4628 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4629 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4630 std::set<INTERP_KERNEL::NormalizedCellType> types;
4631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4632 isChanged->alloc(0,1);
4633 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4635 int pos=nodalConnecOut->getNumberOfTuples();
4636 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4637 isChanged->pushBackSilent(i);
4638 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4639 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4641 if(isChanged->empty())
4643 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4645 return isChanged.retn();
4649 * This method is \b NOT const because it can modify \a this.
4650 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4651 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4652 * \param policy specifies the type of extrusion chosen:
4653 * - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4654 * will be repeated to build each level
4655 * - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4656 * the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4657 * along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4659 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4661 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4663 checkFullyDefined();
4664 mesh1D->checkFullyDefined();
4665 if(!mesh1D->isContiguous1D())
4666 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4667 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4668 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4669 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4670 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4671 if(mesh1D->getMeshDimension()!=1)
4672 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4674 if(isPresenceOfQuadratic())
4676 if(mesh1D->isFullyQuadratic())
4679 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4681 int oldNbOfNodes(getNumberOfNodes());
4682 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4687 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4692 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4696 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4698 setCoords(newCoords);
4699 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4705 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4706 * If it is not the case an exception will be thrown.
4707 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4708 * intersection of plane defined by ('origin','vec').
4709 * This method has one in/out parameter : 'cut3DCurve'.
4710 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4711 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4712 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4713 * This method will throw an exception if \a this contains a non linear segment.
4715 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4717 checkFullyDefined();
4718 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4720 int ncells=getNumberOfCells();
4721 int nnodes=getNumberOfNodes();
4722 double vec2[3],vec3[3],vec4[3];
4723 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4725 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4726 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4727 const int *conn=_nodal_connec->getConstPointer();
4728 const int *connI=_nodal_connec_index->getConstPointer();
4729 const double *coo=_coords->getConstPointer();
4730 std::vector<double> addCoo;
4731 for(int i=0;i<ncells;i++)
4733 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4735 if(cut3DCurve[i]==-2)
4737 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4738 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];
4739 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4740 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4741 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4743 const double *st2=coo+3*st;
4744 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4745 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]));
4746 if(pos>eps && pos<1-eps)
4748 int nNode=((int)addCoo.size())/3;
4749 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4750 addCoo.insert(addCoo.end(),vec4,vec4+3);
4751 cut3DCurve[i]=nnodes+nNode;
4757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4761 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4762 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4763 coo2->alloc(newNbOfNodes,3);
4764 double *tmp=coo2->getPointer();
4765 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4766 std::copy(addCoo.begin(),addCoo.end(),tmp);
4767 DataArrayDouble::SetArrayIn(coo2,_coords);
4772 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4773 * \param mesh1D is the input 1D mesh used for translation computation.
4774 * \return newCoords new coords filled by this method.
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4778 int oldNbOfNodes=getNumberOfNodes();
4779 int nbOf1DCells=mesh1D->getNumberOfCells();
4780 int spaceDim=getSpaceDimension();
4781 DataArrayDouble *ret=DataArrayDouble::New();
4782 std::vector<bool> isQuads;
4783 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4784 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4785 double *retPtr=ret->getPointer();
4786 const double *coords=getCoords()->getConstPointer();
4787 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4789 std::vector<double> c;
4793 for(int i=0;i<nbOf1DCells;i++)
4796 mesh1D->getNodeIdsOfCell(i,v);
4798 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4799 mesh1D->getCoordinatesOfNode(v[0],c);
4800 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4801 for(int j=0;j<oldNbOfNodes;j++)
4802 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4806 mesh1D->getCoordinatesOfNode(v[1],c);
4807 mesh1D->getCoordinatesOfNode(v[0],c);
4808 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4809 for(int j=0;j<oldNbOfNodes;j++)
4810 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4813 ret->copyStringInfoFrom(*getCoords());
4818 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4819 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4820 * \return newCoords new coords filled by this method.
4822 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4824 if(mesh1D->getSpaceDimension()==2)
4825 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4826 if(mesh1D->getSpaceDimension()==3)
4827 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4828 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4832 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4833 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4834 * \return newCoords new coords filled by this method.
4836 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4840 int oldNbOfNodes=getNumberOfNodes();
4841 int nbOf1DCells=mesh1D->getNumberOfCells();
4843 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4844 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4845 int nbOfLevsInVec=nbOf1DCells+1;
4846 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4847 double *retPtr=ret->getPointer();
4848 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4849 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4850 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4851 tmp->setCoords(tmp2);
4852 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4853 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4854 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4855 for(int i=1;i<nbOfLevsInVec;i++)
4857 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4858 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4859 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4860 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4861 tmp->translate(vec);
4862 double tmp3[2],radius,alpha,alpha0;
4863 const double *p0=i+1<nbOfLevsInVec?begin:third;
4864 const double *p1=i+1<nbOfLevsInVec?end:begin;
4865 const double *p2=i+1<nbOfLevsInVec?third:end;
4866 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4867 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]);
4868 double angle=acos(cosangle/(radius*radius));
4869 tmp->rotate(end,0,angle);
4870 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4876 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4877 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4878 * \return newCoords new coords filled by this method.
4880 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4883 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4884 int oldNbOfNodes=getNumberOfNodes();
4885 int nbOf1DCells=mesh1D->getNumberOfCells();
4887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4888 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4889 int nbOfLevsInVec=nbOf1DCells+1;
4890 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4891 double *retPtr=ret->getPointer();
4892 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4893 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4894 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4895 tmp->setCoords(tmp2);
4896 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4897 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4898 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4899 for(int i=1;i<nbOfLevsInVec;i++)
4901 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4902 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4903 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4904 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4905 tmp->translate(vec);
4906 double tmp3[2],radius,alpha,alpha0;
4907 const double *p0=i+1<nbOfLevsInVec?begin:third;
4908 const double *p1=i+1<nbOfLevsInVec?end:begin;
4909 const double *p2=i+1<nbOfLevsInVec?third:end;
4910 double vecPlane[3]={
4911 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4912 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4913 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4915 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4918 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4919 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4920 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4922 double c2=cos(asin(s2));
4924 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4925 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4926 {-vec2[1]*s2, vec2[0]*s2, c2}
4928 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]};
4929 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]};
4930 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]};
4931 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4932 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]);
4933 double angle=acos(cosangle/(radius*radius));
4934 tmp->rotate(end,vecPlane,angle);
4936 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4942 * This method is private because not easy to use for end user. This method is const contrary to
4943 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4944 * the coords sorted slice by slice.
4945 * \param isQuad specifies presence of quadratic cells.
4947 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4949 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4950 int nbOf2DCells(getNumberOfCells());
4951 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4952 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4953 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4955 newConnI->alloc(nbOf3DCells+1,1);
4956 int *newConnIPtr(newConnI->getPointer());
4958 std::vector<int> newc;
4959 for(int j=0;j<nbOf2DCells;j++)
4961 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4962 *newConnIPtr++=(int)newc.size();
4964 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4965 int *newConnPtr(newConn->getPointer());
4966 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4967 newConnIPtr=newConnI->getPointer();
4968 for(int iz=0;iz<nbOf1DCells;iz++)
4971 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4972 const int *posOfTypeOfCell(newConnIPtr);
4973 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4975 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4976 if(icell!=*posOfTypeOfCell)
4979 *newConnPtr=(*iter)+iz*deltaPerLev;
4990 ret->setConnectivity(newConn,newConnI,true);
4991 ret->setCoords(getCoords());
4996 * Checks if \a this mesh is constituted by only quadratic cells.
4997 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4998 * \throw If the coordinates array is not set.
4999 * \throw If the nodal connectivity of cells is not defined.
5001 bool MEDCouplingUMesh::isFullyQuadratic() const
5003 checkFullyDefined();
5005 int nbOfCells=getNumberOfCells();
5006 for(int i=0;i<nbOfCells && ret;i++)
5008 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5009 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5010 ret=cm.isQuadratic();
5016 * Checks if \a this mesh includes any quadratic cell.
5017 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5018 * \throw If the coordinates array is not set.
5019 * \throw If the nodal connectivity of cells is not defined.
5021 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5023 checkFullyDefined();
5025 int nbOfCells=getNumberOfCells();
5026 for(int i=0;i<nbOfCells && !ret;i++)
5028 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5029 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5030 ret=cm.isQuadratic();
5036 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5037 * this mesh, it remains unchanged.
5038 * \throw If the coordinates array is not set.
5039 * \throw If the nodal connectivity of cells is not defined.
5041 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5043 checkFullyDefined();
5044 int nbOfCells=getNumberOfCells();
5046 const int *iciptr=_nodal_connec_index->getConstPointer();
5047 for(int i=0;i<nbOfCells;i++)
5049 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5050 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5051 if(cm.isQuadratic())
5053 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5054 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5055 if(!cml.isDynamic())
5056 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5058 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5064 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5065 const int *icptr=_nodal_connec->getConstPointer();
5066 newConn->alloc(getMeshLength()-delta,1);
5067 newConnI->alloc(nbOfCells+1,1);
5068 int *ocptr=newConn->getPointer();
5069 int *ociptr=newConnI->getPointer();
5072 for(int i=0;i<nbOfCells;i++,ociptr++)
5074 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5075 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5076 if(!cm.isQuadratic())
5078 _types.insert(type);
5079 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5080 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5084 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5085 _types.insert(typel);
5086 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5087 int newNbOfNodes=cml.getNumberOfNodes();
5089 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5090 *ocptr++=(int)typel;
5091 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5092 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5095 setConnectivity(newConn,newConnI,false);
5099 * This method converts all linear cell in \a this to quadratic one.
5100 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5101 * 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)
5102 * 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.
5103 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5104 * end of the existing coordinates.
5106 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5107 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5108 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5110 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5112 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5114 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5116 DataArrayInt *conn=0,*connI=0;
5117 DataArrayDouble *coords=0;
5118 std::set<INTERP_KERNEL::NormalizedCellType> types;
5119 checkFullyDefined();
5120 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5121 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5122 int meshDim=getMeshDimension();
5123 switch(conversionType)
5129 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5130 connSafe=conn; connISafe=connI; coordsSafe=coords;
5133 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5134 connSafe=conn; connISafe=connI; coordsSafe=coords;
5137 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5138 connSafe=conn; connISafe=connI; coordsSafe=coords;
5141 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5149 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5150 connSafe=conn; connISafe=connI; coordsSafe=coords;
5153 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5154 connSafe=conn; connISafe=connI; coordsSafe=coords;
5157 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5158 connSafe=conn; connISafe=connI; coordsSafe=coords;
5161 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5166 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5168 setConnectivity(connSafe,connISafe,false);
5170 setCoords(coordsSafe);
5175 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5176 * so that the number of cells remains the same. Quadratic faces are converted to
5177 * polygons. This method works only for 2D meshes in
5178 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5179 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5180 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5181 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5182 * a polylinized edge constituting the input polygon.
5183 * \throw If the coordinates array is not set.
5184 * \throw If the nodal connectivity of cells is not defined.
5185 * \throw If \a this->getMeshDimension() != 2.
5186 * \throw If \a this->getSpaceDimension() != 2.
5188 void MEDCouplingUMesh::tessellate2D(double eps)
5190 int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5192 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5196 return tessellate2DCurveInternal(eps);
5198 return tessellate2DInternal(eps);
5200 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5204 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5205 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5206 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5207 * a sub-divided edge.
5208 * \throw If the coordinates array is not set.
5209 * \throw If the nodal connectivity of cells is not defined.
5210 * \throw If \a this->getMeshDimension() != 1.
5211 * \throw If \a this->getSpaceDimension() != 2.
5216 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5217 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5218 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5219 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5220 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5221 * This method can be seen as the opposite method of colinearize2D.
5222 * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5223 * to avoid to modify the numbering of existing nodes.
5225 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5226 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5227 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5228 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5229 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5230 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5231 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5233 * \sa buildDescendingConnectivity2
5235 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5236 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5238 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5239 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5240 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5241 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5242 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5243 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5244 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5245 //DataArrayInt *out0(0),*outi0(0);
5246 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5247 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5248 //out0s=out0s->buildUnique(); out0s->sort(true);
5253 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5259 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5263 int nbOfCells=getNumberOfCells();
5264 int nbOfNodes=getNumberOfNodes();
5265 const int *cPtr=_nodal_connec->getConstPointer();
5266 const int *icPtr=_nodal_connec_index->getConstPointer();
5267 int lastVal=0,offset=nbOfNodes;
5268 for(int i=0;i<nbOfCells;i++,icPtr++)
5270 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5271 if(type==INTERP_KERNEL::NORM_SEG2)
5273 types.insert(INTERP_KERNEL::NORM_SEG3);
5274 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5275 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5276 newConn->pushBackSilent(offset++);
5278 newConnI->pushBackSilent(lastVal);
5279 ret->pushBackSilent(i);
5284 lastVal+=(icPtr[1]-icPtr[0]);
5285 newConnI->pushBackSilent(lastVal);
5286 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5289 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5290 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5294 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
5296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5300 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5301 DataArrayInt *conn1D=0,*conn1DI=0;
5302 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5303 DataArrayDouble *coordsTmp=0;
5304 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5305 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5307 const int *c1DPtr=conn1D->begin();
5308 const int *c1DIPtr=conn1DI->begin();
5309 int nbOfCells=getNumberOfCells();
5310 const int *cPtr=_nodal_connec->getConstPointer();
5311 const int *icPtr=_nodal_connec_index->getConstPointer();
5313 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5315 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5316 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5317 if(!cm.isQuadratic())
5319 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5320 types.insert(typ2); newConn->pushBackSilent(typ2);
5321 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5322 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5323 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5324 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5325 newConnI->pushBackSilent(lastVal);
5326 ret->pushBackSilent(i);
5331 lastVal+=(icPtr[1]-icPtr[0]);
5332 newConnI->pushBackSilent(lastVal);
5333 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5336 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5341 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5342 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5343 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5345 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5348 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5349 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5352 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5355 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5361 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5362 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5363 DataArrayInt *conn1D=0,*conn1DI=0;
5364 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5365 DataArrayDouble *coordsTmp=0;
5366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5367 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5369 const int *c1DPtr=conn1D->begin();
5370 const int *c1DIPtr=conn1DI->begin();
5371 int nbOfCells=getNumberOfCells();
5372 const int *cPtr=_nodal_connec->getConstPointer();
5373 const int *icPtr=_nodal_connec_index->getConstPointer();
5374 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5375 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5377 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5378 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5379 if(!cm.isQuadratic())
5381 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5382 types.insert(typ2); newConn->pushBackSilent(typ2);
5383 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5384 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5385 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5386 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5387 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5388 newConnI->pushBackSilent(lastVal);
5389 ret->pushBackSilent(i);
5394 lastVal+=(icPtr[1]-icPtr[0]);
5395 newConnI->pushBackSilent(lastVal);
5396 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5399 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5400 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5405 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5406 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5407 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5409 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5411 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5412 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5413 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5416 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5419 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5421 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5423 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5427 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5428 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5429 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5430 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5431 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5434 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5436 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5438 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5439 int nbOfCells=getNumberOfCells();
5440 const int *cPtr=_nodal_connec->getConstPointer();
5441 const int *icPtr=_nodal_connec_index->getConstPointer();
5442 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5443 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5445 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5446 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5447 if(!cm.isQuadratic())
5449 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5450 if(typ2==INTERP_KERNEL::NORM_ERROR)
5452 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5453 throw INTERP_KERNEL::Exception(oss.str().c_str());
5455 types.insert(typ2); newConn->pushBackSilent(typ2);
5456 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5457 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5458 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5459 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5461 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5462 int tmpPos=newConn->getNumberOfTuples();
5463 newConn->pushBackSilent(nodeId2);
5464 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5466 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5467 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5468 newConnI->pushBackSilent(lastVal);
5469 ret->pushBackSilent(i);
5474 lastVal+=(icPtr[1]-icPtr[0]);
5475 newConnI->pushBackSilent(lastVal);
5476 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5481 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5482 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5483 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5484 int *c=newConn->getPointer();
5485 const int *cI(newConnI->begin());
5486 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5487 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5488 offset=coordsTmp2Safe->getNumberOfTuples();
5489 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5490 c[cI[(*elt)+1]-1]+=offset;
5491 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5496 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5497 * In addition, returns an array mapping new cells to old ones. <br>
5498 * This method typically increases the number of cells in \a this mesh
5499 * but the number of nodes remains \b unchanged.
5500 * That's why the 3D splitting policies
5501 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5502 * \param [in] policy - specifies a pattern used for splitting.
5503 * The semantic of \a policy is:
5504 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5505 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5506 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5507 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5510 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5511 * an id of old cell producing it. The caller is to delete this array using
5512 * decrRef() as it is no more needed.
5514 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5515 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5516 * and \a this->getMeshDimension() != 3.
5517 * \throw If \a policy is not one of the four discussed above.
5518 * \throw If the nodal connectivity of cells is not defined.
5519 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5521 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5526 return simplexizePol0();
5528 return simplexizePol1();
5529 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5530 return simplexizePlanarFace5();
5531 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5532 return simplexizePlanarFace6();
5534 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)");
5539 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5540 * - 1D: INTERP_KERNEL::NORM_SEG2
5541 * - 2D: INTERP_KERNEL::NORM_TRI3
5542 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5544 * This method is useful for users that need to use P1 field services as
5545 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5546 * All these methods need mesh support containing only simplex cells.
5547 * \return bool - \c true if there are only simplex cells in \a this mesh.
5548 * \throw If the coordinates array is not set.
5549 * \throw If the nodal connectivity of cells is not defined.
5550 * \throw If \a this->getMeshDimension() < 1.
5552 bool MEDCouplingUMesh::areOnlySimplexCells() const
5554 checkFullyDefined();
5555 int mdim=getMeshDimension();
5556 if(mdim<1 || mdim>3)
5557 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5558 int nbCells=getNumberOfCells();
5559 const int *conn=_nodal_connec->getConstPointer();
5560 const int *connI=_nodal_connec_index->getConstPointer();
5561 for(int i=0;i<nbCells;i++)
5563 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5571 * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5573 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5575 checkConnectivityFullyDefined();
5576 if(getMeshDimension()!=2)
5577 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5578 int nbOfCells=getNumberOfCells();
5579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5580 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5581 ret->alloc(nbOfCells+nbOfCutCells,1);
5582 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5583 int *retPt=ret->getPointer();
5584 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5585 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5586 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5587 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5588 int *pt=newConn->getPointer();
5589 int *ptI=newConnI->getPointer();
5591 const int *oldc=_nodal_connec->getConstPointer();
5592 const int *ci=_nodal_connec_index->getConstPointer();
5593 for(int i=0;i<nbOfCells;i++,ci++)
5595 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5597 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5598 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5599 pt=std::copy(tmp,tmp+8,pt);
5608 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5609 ptI[1]=ptI[0]+ci[1]-ci[0];
5614 _nodal_connec->decrRef();
5615 _nodal_connec=newConn.retn();
5616 _nodal_connec_index->decrRef();
5617 _nodal_connec_index=newConnI.retn();
5624 * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5626 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5628 checkConnectivityFullyDefined();
5629 if(getMeshDimension()!=2)
5630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5631 int nbOfCells=getNumberOfCells();
5632 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5633 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5634 ret->alloc(nbOfCells+nbOfCutCells,1);
5635 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5636 int *retPt=ret->getPointer();
5637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5639 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5640 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5641 int *pt=newConn->getPointer();
5642 int *ptI=newConnI->getPointer();
5644 const int *oldc=_nodal_connec->getConstPointer();
5645 const int *ci=_nodal_connec_index->getConstPointer();
5646 for(int i=0;i<nbOfCells;i++,ci++)
5648 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5650 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5651 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5652 pt=std::copy(tmp,tmp+8,pt);
5661 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5662 ptI[1]=ptI[0]+ci[1]-ci[0];
5667 _nodal_connec->decrRef();
5668 _nodal_connec=newConn.retn();
5669 _nodal_connec_index->decrRef();
5670 _nodal_connec_index=newConnI.retn();
5677 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5679 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5681 checkConnectivityFullyDefined();
5682 if(getMeshDimension()!=3)
5683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5684 int nbOfCells=getNumberOfCells();
5685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5686 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5687 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5688 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5689 int *retPt=ret->getPointer();
5690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5691 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5692 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5693 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5694 int *pt=newConn->getPointer();
5695 int *ptI=newConnI->getPointer();
5697 const int *oldc=_nodal_connec->getConstPointer();
5698 const int *ci=_nodal_connec_index->getConstPointer();
5699 for(int i=0;i<nbOfCells;i++,ci++)
5701 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5703 for(int j=0;j<5;j++,pt+=5,ptI++)
5705 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5706 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];
5713 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5714 ptI[1]=ptI[0]+ci[1]-ci[0];
5719 _nodal_connec->decrRef();
5720 _nodal_connec=newConn.retn();
5721 _nodal_connec_index->decrRef();
5722 _nodal_connec_index=newConnI.retn();
5729 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5731 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5733 checkConnectivityFullyDefined();
5734 if(getMeshDimension()!=3)
5735 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5736 int nbOfCells=getNumberOfCells();
5737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5738 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5739 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5740 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5741 int *retPt=ret->getPointer();
5742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5744 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5745 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5746 int *pt=newConn->getPointer();
5747 int *ptI=newConnI->getPointer();
5749 const int *oldc=_nodal_connec->getConstPointer();
5750 const int *ci=_nodal_connec_index->getConstPointer();
5751 for(int i=0;i<nbOfCells;i++,ci++)
5753 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5755 for(int j=0;j<6;j++,pt+=5,ptI++)
5757 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5758 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];
5765 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5766 ptI[1]=ptI[0]+ci[1]-ci[0];
5771 _nodal_connec->decrRef();
5772 _nodal_connec=newConn.retn();
5773 _nodal_connec_index->decrRef();
5774 _nodal_connec_index=newConnI.retn();
5781 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5782 * so that the number of cells remains the same. Quadratic faces are converted to
5783 * polygons. This method works only for 2D meshes in
5784 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5785 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5786 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5787 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5788 * a polylinized edge constituting the input polygon.
5789 * \throw If the coordinates array is not set.
5790 * \throw If the nodal connectivity of cells is not defined.
5791 * \throw If \a this->getMeshDimension() != 2.
5792 * \throw If \a this->getSpaceDimension() != 2.
5794 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5796 checkFullyDefined();
5797 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5798 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5799 double epsa=fabs(eps);
5800 if(epsa<std::numeric_limits<double>::min())
5801 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5802 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5803 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5804 revDesc1=0; revDescIndx1=0;
5805 mDesc->tessellate2D(eps);
5806 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5807 setCoords(mDesc->getCoords());
5811 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5812 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5813 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5814 * a sub-divided edge.
5815 * \throw If the coordinates array is not set.
5816 * \throw If the nodal connectivity of cells is not defined.
5817 * \throw If \a this->getMeshDimension() != 1.
5818 * \throw If \a this->getSpaceDimension() != 2.
5820 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5822 checkFullyDefined();
5823 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5825 double epsa=fabs(eps);
5826 if(epsa<std::numeric_limits<double>::min())
5827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5828 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5829 int nbCells=getNumberOfCells();
5830 int nbNodes=getNumberOfNodes();
5831 const int *conn=_nodal_connec->getConstPointer();
5832 const int *connI=_nodal_connec_index->getConstPointer();
5833 const double *coords=_coords->getConstPointer();
5834 std::vector<double> addCoo;
5835 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5837 newConnI->alloc(nbCells+1,1);
5838 int *newConnIPtr=newConnI->getPointer();
5841 INTERP_KERNEL::Node *tmp2[3];
5842 std::set<INTERP_KERNEL::NormalizedCellType> types;
5843 for(int i=0;i<nbCells;i++,newConnIPtr++)
5845 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5846 if(cm.isQuadratic())
5847 {//assert(connI[i+1]-connI[i]-1==3)
5848 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5849 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5850 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5851 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5852 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5855 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5856 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5858 newConnIPtr[1]=(int)newConn.size();
5862 types.insert(INTERP_KERNEL::NORM_SEG2);
5863 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5864 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5865 newConnIPtr[1]=newConnIPtr[0]+3;
5870 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5871 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5872 newConnIPtr[1]=newConnIPtr[0]+3;
5875 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5878 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5880 newConnArr->alloc((int)newConn.size(),1);
5881 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5882 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5883 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5884 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5885 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5886 std::copy(addCoo.begin(),addCoo.end(),work);
5887 DataArrayDouble::SetArrayIn(newCoords,_coords);
5892 * 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.
5893 * This method completly ignore coordinates.
5894 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5895 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5896 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5897 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5899 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5901 checkFullyDefined();
5902 if(getMeshDimension()!=2)
5903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5904 int nbOfCells=getNumberOfCells();
5905 int *connI=_nodal_connec_index->getPointer();
5907 for(int i=0;i<nbOfCells;i++,connI++)
5909 int offset=descIndex[i];
5910 int nbOfEdges=descIndex[i+1]-offset;
5912 bool ddirect=desc[offset+nbOfEdges-1]>0;
5913 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5914 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5915 for(int j=0;j<nbOfEdges;j++)
5917 bool direct=desc[offset+j]>0;
5918 int edgeId=std::abs(desc[offset+j])-1;
5919 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5921 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5922 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5923 int ref2=direct?id1:id2;
5926 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5927 newConnLgth+=nbOfSubNodes-1;
5932 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5933 throw INTERP_KERNEL::Exception(oss.str().c_str());
5938 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5941 newConnLgth++;//+1 is for cell type
5942 connI[1]=newConnLgth;
5945 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5946 newConn->alloc(newConnLgth,1);
5947 int *work=newConn->getPointer();
5948 for(int i=0;i<nbOfCells;i++)
5950 *work++=INTERP_KERNEL::NORM_POLYGON;
5951 int offset=descIndex[i];
5952 int nbOfEdges=descIndex[i+1]-offset;
5953 for(int j=0;j<nbOfEdges;j++)
5955 bool direct=desc[offset+j]>0;
5956 int edgeId=std::abs(desc[offset+j])-1;
5958 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5961 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5962 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5963 work=std::copy(it,it+nbOfSubNodes-1,work);
5967 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5970 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5974 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5975 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5976 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5977 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5978 * so it can be useful to call mergeNodes() before calling this method.
5979 * \throw If \a this->getMeshDimension() <= 1.
5980 * \throw If the coordinates array is not set.
5981 * \throw If the nodal connectivity of cells is not defined.
5983 void MEDCouplingUMesh::convertDegeneratedCells()
5985 checkFullyDefined();
5986 if(getMeshDimension()<=1)
5987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5988 int nbOfCells=getNumberOfCells();
5991 int initMeshLgth=getMeshLength();
5992 int *conn=_nodal_connec->getPointer();
5993 int *index=_nodal_connec_index->getPointer();
5997 for(int i=0;i<nbOfCells;i++)
5999 lgthOfCurCell=index[i+1]-posOfCurCell;
6000 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6002 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6003 conn+newPos+1,newLgth);
6004 conn[newPos]=newType;
6006 posOfCurCell=index[i+1];
6009 if(newPos!=initMeshLgth)
6010 _nodal_connec->reAlloc(newPos);
6015 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6016 * A cell is considered to be oriented correctly if an angle between its
6017 * normal vector and a given vector is less than \c PI / \c 2.
6018 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6020 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6022 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6023 * is not cleared before filling in.
6024 * \throw If \a this->getMeshDimension() != 2.
6025 * \throw If \a this->getSpaceDimension() != 3.
6027 * \if ENABLE_EXAMPLES
6028 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6029 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6032 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6034 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6035 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6036 int nbOfCells=getNumberOfCells();
6037 const int *conn=_nodal_connec->getConstPointer();
6038 const int *connI=_nodal_connec_index->getConstPointer();
6039 const double *coordsPtr=_coords->getConstPointer();
6040 for(int i=0;i<nbOfCells;i++)
6042 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6043 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6045 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6046 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6053 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6054 * considered to be oriented correctly if an angle between its normal vector and a
6055 * given vector is less than \c PI / \c 2.
6056 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6058 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6060 * \throw If \a this->getMeshDimension() != 2.
6061 * \throw If \a this->getSpaceDimension() != 3.
6063 * \if ENABLE_EXAMPLES
6064 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6065 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6068 * \sa changeOrientationOfCells
6070 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6072 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6073 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6074 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6075 const int *connI(_nodal_connec_index->getConstPointer());
6076 const double *coordsPtr(_coords->getConstPointer());
6077 bool isModified(false);
6078 for(int i=0;i<nbOfCells;i++)
6080 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6081 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6083 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6084 bool isQuadratic(cm.isQuadratic());
6085 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6088 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6093 _nodal_connec->declareAsNew();
6098 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6100 * \sa orientCorrectly2DCells
6102 void MEDCouplingUMesh::changeOrientationOfCells()
6104 int mdim(getMeshDimension());
6105 if(mdim!=2 && mdim!=1)
6106 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6107 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6108 const int *connI(_nodal_connec_index->getConstPointer());
6111 for(int i=0;i<nbOfCells;i++)
6113 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6114 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6115 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6120 for(int i=0;i<nbOfCells;i++)
6122 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6123 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6124 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6130 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6131 * oriented facets. The normal vector of the facet should point out of the cell.
6132 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6133 * is not cleared before filling in.
6134 * \throw If \a this->getMeshDimension() != 3.
6135 * \throw If \a this->getSpaceDimension() != 3.
6136 * \throw If the coordinates array is not set.
6137 * \throw If the nodal connectivity of cells is not defined.
6139 * \if ENABLE_EXAMPLES
6140 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6141 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6144 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6146 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6147 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6148 int nbOfCells=getNumberOfCells();
6149 const int *conn=_nodal_connec->getConstPointer();
6150 const int *connI=_nodal_connec_index->getConstPointer();
6151 const double *coordsPtr=_coords->getConstPointer();
6152 for(int i=0;i<nbOfCells;i++)
6154 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6155 if(type==INTERP_KERNEL::NORM_POLYHED)
6157 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6164 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6166 * \throw If \a this->getMeshDimension() != 3.
6167 * \throw If \a this->getSpaceDimension() != 3.
6168 * \throw If the coordinates array is not set.
6169 * \throw If the nodal connectivity of cells is not defined.
6170 * \throw If the reparation fails.
6172 * \if ENABLE_EXAMPLES
6173 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6174 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6176 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6178 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6180 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6181 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6182 int nbOfCells=getNumberOfCells();
6183 int *conn=_nodal_connec->getPointer();
6184 const int *connI=_nodal_connec_index->getConstPointer();
6185 const double *coordsPtr=_coords->getConstPointer();
6186 for(int i=0;i<nbOfCells;i++)
6188 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6189 if(type==INTERP_KERNEL::NORM_POLYHED)
6193 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6194 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6196 catch(INTERP_KERNEL::Exception& e)
6198 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6199 throw INTERP_KERNEL::Exception(oss.str().c_str());
6207 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6208 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6209 * according to which the first facet of the cell should be oriented to have the normal vector
6210 * pointing out of cell.
6211 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6212 * cells. The caller is to delete this array using decrRef() as it is no more
6214 * \throw If \a this->getMeshDimension() != 3.
6215 * \throw If \a this->getSpaceDimension() != 3.
6216 * \throw If the coordinates array is not set.
6217 * \throw If the nodal connectivity of cells is not defined.
6219 * \if ENABLE_EXAMPLES
6220 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6221 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6223 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6225 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6227 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6228 if(getMeshDimension()!=3)
6229 throw INTERP_KERNEL::Exception(msg);
6230 int spaceDim=getSpaceDimension();
6232 throw INTERP_KERNEL::Exception(msg);
6234 int nbOfCells=getNumberOfCells();
6235 int *conn=_nodal_connec->getPointer();
6236 const int *connI=_nodal_connec_index->getConstPointer();
6237 const double *coo=getCoords()->getConstPointer();
6238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6239 for(int i=0;i<nbOfCells;i++)
6241 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6242 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6244 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6246 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6247 cells->pushBackSilent(i);
6251 return cells.retn();
6255 * This method is a faster method to correct orientation of all 3D cells in \a this.
6256 * 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.
6257 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency1 should throw no exception.
6259 * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6260 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6262 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6264 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6265 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6266 int nbOfCells=getNumberOfCells();
6267 int *conn=_nodal_connec->getPointer();
6268 const int *connI=_nodal_connec_index->getConstPointer();
6269 const double *coordsPtr=_coords->getConstPointer();
6270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6271 for(int i=0;i<nbOfCells;i++)
6273 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6276 case INTERP_KERNEL::NORM_TETRA4:
6278 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6280 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6281 ret->pushBackSilent(i);
6285 case INTERP_KERNEL::NORM_PYRA5:
6287 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6289 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6290 ret->pushBackSilent(i);
6294 case INTERP_KERNEL::NORM_PENTA6:
6295 case INTERP_KERNEL::NORM_HEXA8:
6296 case INTERP_KERNEL::NORM_HEXGP12:
6298 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6300 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6301 ret->pushBackSilent(i);
6305 case INTERP_KERNEL::NORM_POLYHED:
6307 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6309 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6310 ret->pushBackSilent(i);
6315 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 !");
6323 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6324 * If it is not the case an exception will be thrown.
6325 * This method is fast because the first cell of \a this is used to compute the plane.
6326 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6327 * \param pos output of size at least 3 used to store a point owned of searched plane.
6329 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6331 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6332 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6333 const int *conn=_nodal_connec->getConstPointer();
6334 const int *connI=_nodal_connec_index->getConstPointer();
6335 const double *coordsPtr=_coords->getConstPointer();
6336 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6337 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6341 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6342 * cells. Currently cells of the following types are treated:
6343 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6344 * For a cell of other type an exception is thrown.
6345 * Space dimension of a 2D mesh can be either 2 or 3.
6346 * The Edge Ratio of a cell \f$t\f$ is:
6347 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6348 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6349 * the smallest edge lengths of \f$t\f$.
6350 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6351 * cells and one time, lying on \a this mesh. The caller is to delete this
6352 * field using decrRef() as it is no more needed.
6353 * \throw If the coordinates array is not set.
6354 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6355 * \throw If the connectivity data array has more than one component.
6356 * \throw If the connectivity data array has a named component.
6357 * \throw If the connectivity index data array has more than one component.
6358 * \throw If the connectivity index data array has a named component.
6359 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6360 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6361 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6363 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6366 int spaceDim=getSpaceDimension();
6367 int meshDim=getMeshDimension();
6368 if(spaceDim!=2 && spaceDim!=3)
6369 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6370 if(meshDim!=2 && meshDim!=3)
6371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6372 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6374 int nbOfCells=getNumberOfCells();
6375 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6376 arr->alloc(nbOfCells,1);
6377 double *pt=arr->getPointer();
6378 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6379 const int *conn=_nodal_connec->getConstPointer();
6380 const int *connI=_nodal_connec_index->getConstPointer();
6381 const double *coo=_coords->getConstPointer();
6383 for(int i=0;i<nbOfCells;i++,pt++)
6385 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6388 case INTERP_KERNEL::NORM_TRI3:
6390 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6391 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6394 case INTERP_KERNEL::NORM_QUAD4:
6396 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6397 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6400 case INTERP_KERNEL::NORM_TETRA4:
6402 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6403 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6407 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6409 conn+=connI[i+1]-connI[i];
6411 ret->setName("EdgeRatio");
6412 ret->synchronizeTimeWithSupport();
6417 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6418 * cells. Currently cells of the following types are treated:
6419 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6420 * For a cell of other type an exception is thrown.
6421 * Space dimension of a 2D mesh can be either 2 or 3.
6422 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6423 * cells and one time, lying on \a this mesh. The caller is to delete this
6424 * field using decrRef() as it is no more needed.
6425 * \throw If the coordinates array is not set.
6426 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6427 * \throw If the connectivity data array has more than one component.
6428 * \throw If the connectivity data array has a named component.
6429 * \throw If the connectivity index data array has more than one component.
6430 * \throw If the connectivity index data array has a named component.
6431 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6432 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6433 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6435 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6438 int spaceDim=getSpaceDimension();
6439 int meshDim=getMeshDimension();
6440 if(spaceDim!=2 && spaceDim!=3)
6441 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6442 if(meshDim!=2 && meshDim!=3)
6443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6444 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6446 int nbOfCells=getNumberOfCells();
6447 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6448 arr->alloc(nbOfCells,1);
6449 double *pt=arr->getPointer();
6450 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6451 const int *conn=_nodal_connec->getConstPointer();
6452 const int *connI=_nodal_connec_index->getConstPointer();
6453 const double *coo=_coords->getConstPointer();
6455 for(int i=0;i<nbOfCells;i++,pt++)
6457 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6460 case INTERP_KERNEL::NORM_TRI3:
6462 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6463 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6466 case INTERP_KERNEL::NORM_QUAD4:
6468 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6469 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6472 case INTERP_KERNEL::NORM_TETRA4:
6474 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6475 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6479 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6481 conn+=connI[i+1]-connI[i];
6483 ret->setName("AspectRatio");
6484 ret->synchronizeTimeWithSupport();
6489 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6490 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6491 * treated: INTERP_KERNEL::NORM_QUAD4.
6492 * For a cell of other type an exception is thrown.
6493 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6494 * cells and one time, lying on \a this mesh. The caller is to delete this
6495 * field using decrRef() as it is no more needed.
6496 * \throw If the coordinates array is not set.
6497 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6498 * \throw If the connectivity data array has more than one component.
6499 * \throw If the connectivity data array has a named component.
6500 * \throw If the connectivity index data array has more than one component.
6501 * \throw If the connectivity index data array has a named component.
6502 * \throw If \a this->getMeshDimension() != 2.
6503 * \throw If \a this->getSpaceDimension() != 3.
6504 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6506 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6509 int spaceDim=getSpaceDimension();
6510 int meshDim=getMeshDimension();
6512 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6514 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6515 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6517 int nbOfCells=getNumberOfCells();
6518 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6519 arr->alloc(nbOfCells,1);
6520 double *pt=arr->getPointer();
6521 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6522 const int *conn=_nodal_connec->getConstPointer();
6523 const int *connI=_nodal_connec_index->getConstPointer();
6524 const double *coo=_coords->getConstPointer();
6526 for(int i=0;i<nbOfCells;i++,pt++)
6528 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6531 case INTERP_KERNEL::NORM_QUAD4:
6533 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6534 *pt=INTERP_KERNEL::quadWarp(tmp);
6538 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6540 conn+=connI[i+1]-connI[i];
6542 ret->setName("Warp");
6543 ret->synchronizeTimeWithSupport();
6549 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6550 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6551 * treated: INTERP_KERNEL::NORM_QUAD4.
6552 * For a cell of other type an exception is thrown.
6553 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6554 * cells and one time, lying on \a this mesh. The caller is to delete this
6555 * field using decrRef() as it is no more needed.
6556 * \throw If the coordinates array is not set.
6557 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6558 * \throw If the connectivity data array has more than one component.
6559 * \throw If the connectivity data array has a named component.
6560 * \throw If the connectivity index data array has more than one component.
6561 * \throw If the connectivity index data array has a named component.
6562 * \throw If \a this->getMeshDimension() != 2.
6563 * \throw If \a this->getSpaceDimension() != 3.
6564 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6566 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6569 int spaceDim=getSpaceDimension();
6570 int meshDim=getMeshDimension();
6572 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6574 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6575 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6577 int nbOfCells=getNumberOfCells();
6578 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6579 arr->alloc(nbOfCells,1);
6580 double *pt=arr->getPointer();
6581 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6582 const int *conn=_nodal_connec->getConstPointer();
6583 const int *connI=_nodal_connec_index->getConstPointer();
6584 const double *coo=_coords->getConstPointer();
6586 for(int i=0;i<nbOfCells;i++,pt++)
6588 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6591 case INTERP_KERNEL::NORM_QUAD4:
6593 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6594 *pt=INTERP_KERNEL::quadSkew(tmp);
6598 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6600 conn+=connI[i+1]-connI[i];
6602 ret->setName("Skew");
6603 ret->synchronizeTimeWithSupport();
6608 * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
6610 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6612 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6614 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6617 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6619 std::set<INTERP_KERNEL::NormalizedCellType> types;
6620 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6621 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6622 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6623 arr->alloc(nbCells,1);
6624 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6626 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6627 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6628 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6631 ret->setName("Diameter");
6636 * This method aggregate the bbox of each cell and put it into bbox parameter.
6638 * \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)
6639 * For all other cases this input parameter is ignored.
6640 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6642 * \throw If \a this is not fully set (coordinates and connectivity).
6643 * \throw If a cell in \a this has no valid nodeId.
6644 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6646 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6648 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6649 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.
6650 return getBoundingBoxForBBTreeFast();
6651 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6653 bool presenceOfQuadratic(false);
6654 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6656 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6657 if(cm.isQuadratic())
6658 presenceOfQuadratic=true;
6660 if(!presenceOfQuadratic)
6661 return getBoundingBoxForBBTreeFast();
6662 if(mDim==2 && sDim==2)
6663 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6665 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6667 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) !");
6671 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6672 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6674 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6676 * \throw If \a this is not fully set (coordinates and connectivity).
6677 * \throw If a cell in \a this has no valid nodeId.
6679 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6681 checkFullyDefined();
6682 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6683 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6684 double *bbox(ret->getPointer());
6685 for(int i=0;i<nbOfCells*spaceDim;i++)
6687 bbox[2*i]=std::numeric_limits<double>::max();
6688 bbox[2*i+1]=-std::numeric_limits<double>::max();
6690 const double *coordsPtr(_coords->getConstPointer());
6691 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6692 for(int i=0;i<nbOfCells;i++)
6694 int offset=connI[i]+1;
6695 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6696 for(int j=0;j<nbOfNodesForCell;j++)
6698 int nodeId=conn[offset+j];
6699 if(nodeId>=0 && nodeId<nbOfNodes)
6701 for(int k=0;k<spaceDim;k++)
6703 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6704 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6711 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6712 throw INTERP_KERNEL::Exception(oss.str().c_str());
6719 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6720 * useful for 2D meshes having quadratic cells
6721 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6722 * the two extremities of the arc of circle).
6724 * \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)
6725 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6726 * \throw If \a this is not fully defined.
6727 * \throw If \a this is not a mesh with meshDimension equal to 2.
6728 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6729 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6731 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6733 checkFullyDefined();
6734 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6735 if(spaceDim!=2 || mDim!=2)
6736 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!");
6737 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6738 double *bbox(ret->getPointer());
6739 const double *coords(_coords->getConstPointer());
6740 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6741 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6743 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6744 int sz(connI[1]-connI[0]-1);
6745 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6746 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6747 INTERP_KERNEL::QuadraticPolygon *pol(0);
6748 for(int j=0;j<sz;j++)
6750 int nodeId(conn[*connI+1+j]);
6751 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6753 if(!cm.isQuadratic())
6754 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6756 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6757 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6758 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6764 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6765 * useful for 2D meshes having quadratic cells
6766 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6767 * the two extremities of the arc of circle).
6769 * \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)
6770 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6771 * \throw If \a this is not fully defined.
6772 * \throw If \a this is not a mesh with meshDimension equal to 1.
6773 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6774 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6776 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6778 checkFullyDefined();
6779 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6780 if(spaceDim!=2 || mDim!=1)
6781 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!");
6782 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6783 double *bbox(ret->getPointer());
6784 const double *coords(_coords->getConstPointer());
6785 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6786 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6788 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6789 int sz(connI[1]-connI[0]-1);
6790 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6791 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6792 INTERP_KERNEL::Edge *edge(0);
6793 for(int j=0;j<sz;j++)
6795 int nodeId(conn[*connI+1+j]);
6796 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6798 if(!cm.isQuadratic())
6799 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6801 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6802 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6803 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6810 namespace MEDCouplingImpl
6815 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6816 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6825 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6826 bool operator() (const int& pos) { return _conn[pos]==_val; }
6836 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6837 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6838 * \a this is composed in cell types.
6839 * The returned array is of size 3*n where n is the number of different types present in \a this.
6840 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6841 * This parameter is kept only for compatibility with other methode listed above.
6843 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6845 checkConnectivityFullyDefined();
6846 const int *conn=_nodal_connec->getConstPointer();
6847 const int *connI=_nodal_connec_index->getConstPointer();
6848 const int *work=connI;
6849 int nbOfCells=getNumberOfCells();
6850 std::size_t n=getAllGeoTypes().size();
6851 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6852 std::set<INTERP_KERNEL::NormalizedCellType> types;
6853 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6855 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6856 if(types.find(typ)!=types.end())
6858 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6859 oss << " is not contiguous !";
6860 throw INTERP_KERNEL::Exception(oss.str().c_str());
6864 const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
6865 ret[3*i+1]=(int)std::distance(work,work2);
6872 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6873 * only for types cell, type node is not managed.
6874 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6875 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6876 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6877 * If 2 or more same geometric type is in \a code and exception is thrown too.
6879 * This method firstly checks
6880 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6881 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6882 * an exception is thrown too.
6884 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6885 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6886 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6888 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6892 std::size_t sz=code.size();
6895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6896 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6898 bool isNoPflUsed=true;
6899 for(std::size_t i=0;i<n;i++)
6900 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6902 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6904 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6905 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6906 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6912 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6913 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6914 if(types.size()==_types.size())
6917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6919 int *retPtr=ret->getPointer();
6920 const int *connI=_nodal_connec_index->getConstPointer();
6921 const int *conn=_nodal_connec->getConstPointer();
6922 int nbOfCells=getNumberOfCells();
6925 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6927 i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
6928 int offset=(int)std::distance(connI,i);
6929 const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
6930 int nbOfCellsOfCurType=(int)std::distance(i,j);
6931 if(code[3*kk+2]==-1)
6932 for(int k=0;k<nbOfCellsOfCurType;k++)
6936 int idInIdsPerType=code[3*kk+2];
6937 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6939 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6942 zePfl->checkAllocated();
6943 if(zePfl->getNumberOfComponents()==1)
6945 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6947 if(*k>=0 && *k<nbOfCellsOfCurType)
6948 *retPtr=(*k)+offset;
6951 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6952 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6953 throw INTERP_KERNEL::Exception(oss.str().c_str());
6958 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6961 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6965 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6966 oss << " should be in [0," << idsPerType.size() << ") !";
6967 throw INTERP_KERNEL::Exception(oss.str().c_str());
6976 * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6977 * 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.
6978 * 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.
6979 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6981 * \param [in] profile
6982 * \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.
6983 * \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,
6984 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6985 * \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.
6986 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6987 * \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
6989 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6992 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6993 if(profile->getNumberOfComponents()!=1)
6994 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6995 checkConnectivityFullyDefined();
6996 const int *conn=_nodal_connec->getConstPointer();
6997 const int *connI=_nodal_connec_index->getConstPointer();
6998 int nbOfCells=getNumberOfCells();
6999 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7000 std::vector<int> typeRangeVals(1);
7001 for(const int *i=connI;i!=connI+nbOfCells;)
7003 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7004 if(std::find(types.begin(),types.end(),curType)!=types.end())
7006 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7008 types.push_back(curType);
7009 i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7010 typeRangeVals.push_back((int)std::distance(connI,i));
7013 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7014 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
7016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
7017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
7019 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7020 code.resize(3*nbOfCastsFinal);
7021 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7022 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7023 for(int i=0;i<nbOfCastsFinal;i++)
7025 int castId=castsPresent->getIJ(i,0);
7026 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7027 idsInPflPerType2.push_back(tmp3);
7028 code[3*i]=(int)types[castId];
7029 code[3*i+1]=tmp3->getNumberOfTuples();
7030 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7031 if(!tmp4->isIdentity2(typeRangeVals[castId+1]-typeRangeVals[castId]))
7033 tmp4->copyStringInfoFrom(*profile);
7034 idsPerType2.push_back(tmp4);
7035 code[3*i+2]=(int)idsPerType2.size()-1;
7042 std::size_t sz2=idsInPflPerType2.size();
7043 idsInPflPerType.resize(sz2);
7044 for(std::size_t i=0;i<sz2;i++)
7046 DataArrayInt *locDa=idsInPflPerType2[i];
7048 idsInPflPerType[i]=locDa;
7050 std::size_t sz=idsPerType2.size();
7051 idsPerType.resize(sz);
7052 for(std::size_t i=0;i<sz;i++)
7054 DataArrayInt *locDa=idsPerType2[i];
7056 idsPerType[i]=locDa;
7061 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7062 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7063 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7064 * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::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.
7066 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7068 checkFullyDefined();
7069 nM1LevMesh->checkFullyDefined();
7070 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7071 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7072 if(_coords!=nM1LevMesh->getCoords())
7073 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7075 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7076 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7077 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7078 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7079 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7080 tmp->setConnectivity(tmp0,tmp1);
7081 tmp->renumberCells(ret0->getConstPointer(),false);
7082 revDesc=tmp->getNodalConnectivity();
7083 revDescIndx=tmp->getNodalConnectivityIndex();
7084 DataArrayInt *ret=0;
7085 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7088 ret->getMaxValue(tmp2);
7090 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7091 throw INTERP_KERNEL::Exception(oss.str().c_str());
7096 revDescIndx->incrRef();
7099 meshnM1Old2New=ret0;
7104 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7105 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7106 * in "Old to New" mode.
7107 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7108 * this array using decrRef() as it is no more needed.
7109 * \throw If the nodal connectivity of cells is not defined.
7111 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7113 checkConnectivityFullyDefined();
7114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7115 renumberCells(ret->getConstPointer(),false);
7120 * This methods checks that cells are sorted by their types.
7121 * This method makes asumption (no check) that connectivity is correctly set before calling.
7123 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7125 checkFullyDefined();
7126 const int *conn=_nodal_connec->getConstPointer();
7127 const int *connI=_nodal_connec_index->getConstPointer();
7128 int nbOfCells=getNumberOfCells();
7129 std::set<INTERP_KERNEL::NormalizedCellType> types;
7130 for(const int *i=connI;i!=connI+nbOfCells;)
7132 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7133 if(types.find(curType)!=types.end())
7135 types.insert(curType);
7136 i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7142 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7143 * The geometric type order is specified by MED file.
7145 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7147 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7149 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7153 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7154 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7155 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7156 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7158 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7160 checkFullyDefined();
7161 const int *conn=_nodal_connec->getConstPointer();
7162 const int *connI=_nodal_connec_index->getConstPointer();
7163 int nbOfCells=getNumberOfCells();
7167 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7168 for(const int *i=connI;i!=connI+nbOfCells;)
7170 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7171 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7172 if(isTypeExists!=orderEnd)
7174 int pos=(int)std::distance(orderBg,isTypeExists);
7178 i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7182 if(sg.find(curType)==sg.end())
7184 i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7195 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7196 * 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
7197 * 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'.
7199 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7201 checkConnectivityFullyDefined();
7202 int nbOfCells=getNumberOfCells();
7203 const int *conn=_nodal_connec->getConstPointer();
7204 const int *connI=_nodal_connec_index->getConstPointer();
7205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7207 tmpa->alloc(nbOfCells,1);
7208 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7209 tmpb->fillWithZero();
7210 int *tmp=tmpa->getPointer();
7211 int *tmp2=tmpb->getPointer();
7212 for(const int *i=connI;i!=connI+nbOfCells;i++)
7214 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7217 int pos=(int)std::distance(orderBg,where);
7219 tmp[std::distance(connI,i)]=pos;
7223 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7224 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7225 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7226 throw INTERP_KERNEL::Exception(oss.str().c_str());
7229 nbPerType=tmpb.retn();
7234 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7236 * \return a new object containing the old to new correspondance.
7238 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7240 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7242 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7246 * 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.
7247 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7248 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7249 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7251 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7253 DataArrayInt *nbPerType=0;
7254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7255 nbPerType->decrRef();
7256 return tmpa->buildPermArrPerLevel();
7260 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7261 * The number of cells remains unchanged after the call of this method.
7262 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7263 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7265 * \return the array giving the correspondance old to new.
7267 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7269 checkFullyDefined();
7271 const int *conn=_nodal_connec->getConstPointer();
7272 const int *connI=_nodal_connec_index->getConstPointer();
7273 int nbOfCells=getNumberOfCells();
7274 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7275 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7276 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7278 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7279 types.push_back(curType);
7280 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7282 DataArrayInt *ret=DataArrayInt::New();
7283 ret->alloc(nbOfCells,1);
7284 int *retPtr=ret->getPointer();
7285 std::fill(retPtr,retPtr+nbOfCells,-1);
7287 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7289 for(const int *i=connI;i!=connI+nbOfCells;i++)
7290 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7291 retPtr[std::distance(connI,i)]=newCellId++;
7293 renumberCells(retPtr,false);
7298 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7299 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7300 * This method makes asumption that connectivity is correctly set before calling.
7302 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7304 checkConnectivityFullyDefined();
7305 const int *conn=_nodal_connec->getConstPointer();
7306 const int *connI=_nodal_connec_index->getConstPointer();
7307 int nbOfCells=getNumberOfCells();
7308 std::vector<MEDCouplingUMesh *> ret;
7309 for(const int *i=connI;i!=connI+nbOfCells;)
7311 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7312 int beginCellId=(int)std::distance(connI,i);
7313 i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7314 int endCellId=(int)std::distance(connI,i);
7315 int sz=endCellId-beginCellId;
7316 int *cells=new int[sz];
7317 for(int j=0;j<sz;j++)
7318 cells[j]=beginCellId+j;
7319 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7327 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7328 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7329 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7331 * \return a newly allocated instance, that the caller must manage.
7332 * \throw If \a this contains more than one geometric type.
7333 * \throw If the nodal connectivity of \a this is not fully defined.
7334 * \throw If the internal data is not coherent.
7336 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7338 checkConnectivityFullyDefined();
7339 if(_types.size()!=1)
7340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7341 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7342 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7343 ret->setCoords(getCoords());
7344 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7348 retC->setNodalConnectivity(c);
7352 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7355 DataArrayInt *c=0,*ci=0;
7356 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7358 retD->setNodalConnectivity(cs,cis);
7363 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7365 checkConnectivityFullyDefined();
7366 if(_types.size()!=1)
7367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7368 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7369 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7372 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7373 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7374 throw INTERP_KERNEL::Exception(oss.str().c_str());
7376 int nbCells=getNumberOfCells();
7378 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7380 int *outPtr=connOut->getPointer();
7381 const int *conn=_nodal_connec->begin();
7382 const int *connI=_nodal_connec_index->begin();
7384 for(int i=0;i<nbCells;i++,connI++)
7386 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7387 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7390 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 << ") !";
7391 throw INTERP_KERNEL::Exception(oss.str().c_str());
7394 return connOut.retn();
7398 * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7399 * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7403 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7405 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency1 !";
7406 checkConnectivityFullyDefined();
7407 if(_types.size()!=1)
7408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7409 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7411 throw INTERP_KERNEL::Exception(msg0);
7412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7413 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7414 int *cp(c->getPointer()),*cip(ci->getPointer());
7415 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7417 for(int i=0;i<nbCells;i++,cip++,incip++)
7419 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7420 int delta(stop-strt);
7423 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7424 cp=std::copy(incp+strt,incp+stop,cp);
7426 throw INTERP_KERNEL::Exception(msg0);
7429 throw INTERP_KERNEL::Exception(msg0);
7430 cip[1]=cip[0]+delta;
7432 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7436 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7437 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7438 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7439 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7440 * are not used here to avoid the build of big permutation array.
7442 * \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
7443 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7444 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7445 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7446 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7447 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7448 * \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
7449 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7451 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7452 DataArrayInt *&szOfCellGrpOfSameType,
7453 DataArrayInt *&idInMsOfCellGrpOfSameType)
7455 std::vector<const MEDCouplingUMesh *> ms2;
7456 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7459 (*it)->checkConnectivityFullyDefined();
7463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7464 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7465 int meshDim=ms2[0]->getMeshDimension();
7466 std::vector<const MEDCouplingUMesh *> m1ssm;
7467 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7469 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7470 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7473 ret1->alloc(0,1); ret2->alloc(0,1);
7474 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7476 if(meshDim!=(*it)->getMeshDimension())
7477 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7478 if(refCoo!=(*it)->getCoords())
7479 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7480 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7481 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7482 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7483 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7485 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7486 m1ssmSingleAuto.push_back(singleCell);
7487 m1ssmSingle.push_back(singleCell);
7488 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7491 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7492 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7493 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7494 for(std::size_t i=0;i<m1ssm.size();i++)
7495 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7496 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7497 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7498 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7503 * This method returns a newly created DataArrayInt instance.
7504 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7506 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7508 checkFullyDefined();
7509 const int *conn=_nodal_connec->getConstPointer();
7510 const int *connIndex=_nodal_connec_index->getConstPointer();
7511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7512 for(const int *w=begin;w!=end;w++)
7513 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7514 ret->pushBackSilent(*w);
7519 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7520 * are in [0:getNumberOfCells())
7522 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7524 checkFullyDefined();
7525 const int *conn=_nodal_connec->getConstPointer();
7526 const int *connI=_nodal_connec_index->getConstPointer();
7527 int nbOfCells=getNumberOfCells();
7528 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7529 int *tmp=new int[nbOfCells];
7530 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7533 for(const int *i=connI;i!=connI+nbOfCells;i++)
7534 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7535 tmp[std::distance(connI,i)]=j++;
7537 DataArrayInt *ret=DataArrayInt::New();
7538 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7539 ret->copyStringInfoFrom(*da);
7540 int *retPtr=ret->getPointer();
7541 const int *daPtr=da->getConstPointer();
7542 int nbOfElems=da->getNbOfElems();
7543 for(int k=0;k<nbOfElems;k++)
7544 retPtr[k]=tmp[daPtr[k]];
7550 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7551 * This method \b works \b for mesh sorted by type.
7552 * cells whose ids is in 'idsPerGeoType' array.
7553 * This method conserves coords and name of mesh.
7555 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7557 std::vector<int> code=getDistributionOfTypes();
7558 std::size_t nOfTypesInThis=code.size()/3;
7559 int sz=0,szOfType=0;
7560 for(std::size_t i=0;i<nOfTypesInThis;i++)
7565 szOfType=code[3*i+1];
7567 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7568 if(*work<0 || *work>=szOfType)
7570 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7571 oss << ". It should be in [0," << szOfType << ") !";
7572 throw INTERP_KERNEL::Exception(oss.str().c_str());
7574 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7575 int *idsPtr=idsTokeep->getPointer();
7577 for(std::size_t i=0;i<nOfTypesInThis;i++)
7580 for(int j=0;j<code[3*i+1];j++)
7583 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7584 offset+=code[3*i+1];
7586 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7587 ret->copyTinyInfoFrom(this);
7592 * This method returns a vector of size 'this->getNumberOfCells()'.
7593 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7595 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7597 int ncell=getNumberOfCells();
7598 std::vector<bool> ret(ncell);
7599 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7600 const int *c=getNodalConnectivity()->getConstPointer();
7601 for(int i=0;i<ncell;i++)
7603 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7604 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7605 ret[i]=cm.isQuadratic();
7611 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7613 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7615 if(other->getType()!=UNSTRUCTURED)
7616 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7617 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7618 return MergeUMeshes(this,otherC);
7622 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7623 * computed by averaging coordinates of cell nodes, so this method is not a right
7624 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7625 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7626 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7627 * components. The caller is to delete this array using decrRef() as it is
7629 * \throw If the coordinates array is not set.
7630 * \throw If the nodal connectivity of cells is not defined.
7631 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7633 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7635 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7636 int spaceDim=getSpaceDimension();
7637 int nbOfCells=getNumberOfCells();
7638 ret->alloc(nbOfCells,spaceDim);
7639 ret->copyStringInfoFrom(*getCoords());
7640 double *ptToFill=ret->getPointer();
7641 const int *nodal=_nodal_connec->getConstPointer();
7642 const int *nodalI=_nodal_connec_index->getConstPointer();
7643 const double *coor=_coords->getConstPointer();
7644 for(int i=0;i<nbOfCells;i++)
7646 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7647 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7654 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7655 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7657 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7658 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7660 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7661 * \throw If \a this is not fully defined (coordinates and connectivity)
7662 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7664 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7666 checkFullyDefined();
7667 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7668 int spaceDim=getSpaceDimension();
7669 int nbOfCells=getNumberOfCells();
7670 int nbOfNodes=getNumberOfNodes();
7671 ret->alloc(nbOfCells,spaceDim);
7672 double *ptToFill=ret->getPointer();
7673 const int *nodal=_nodal_connec->getConstPointer();
7674 const int *nodalI=_nodal_connec_index->getConstPointer();
7675 const double *coor=_coords->getConstPointer();
7676 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7678 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7679 std::fill(ptToFill,ptToFill+spaceDim,0.);
7680 if(type!=INTERP_KERNEL::NORM_POLYHED)
7682 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7684 if(*conn>=0 && *conn<nbOfNodes)
7685 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7688 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7689 throw INTERP_KERNEL::Exception(oss.str().c_str());
7692 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7693 if(nbOfNodesInCell>0)
7694 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7697 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7698 throw INTERP_KERNEL::Exception(oss.str().c_str());
7703 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7705 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7707 if(*it>=0 && *it<nbOfNodes)
7708 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7711 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7712 throw INTERP_KERNEL::Exception(oss.str().c_str());
7716 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7719 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7720 throw INTERP_KERNEL::Exception(oss.str().c_str());
7728 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7729 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7730 * are specified via an array of cell ids.
7731 * \warning Validity of the specified cell ids is not checked!
7732 * Valid range is [ 0, \a this->getNumberOfCells() ).
7733 * \param [in] begin - an array of cell ids of interest.
7734 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7735 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7736 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7737 * caller is to delete this array using decrRef() as it is no more needed.
7738 * \throw If the coordinates array is not set.
7739 * \throw If the nodal connectivity of cells is not defined.
7741 * \if ENABLE_EXAMPLES
7742 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7743 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7746 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7748 DataArrayDouble *ret=DataArrayDouble::New();
7749 int spaceDim=getSpaceDimension();
7750 int nbOfTuple=(int)std::distance(begin,end);
7751 ret->alloc(nbOfTuple,spaceDim);
7752 double *ptToFill=ret->getPointer();
7753 double *tmp=new double[spaceDim];
7754 const int *nodal=_nodal_connec->getConstPointer();
7755 const int *nodalI=_nodal_connec_index->getConstPointer();
7756 const double *coor=_coords->getConstPointer();
7757 for(const int *w=begin;w!=end;w++)
7759 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7760 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7768 * 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".
7769 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7770 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7771 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7772 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7774 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7775 * \throw If spaceDim!=3 or meshDim!=2.
7776 * \throw If connectivity of \a this is invalid.
7777 * \throw If connectivity of a cell in \a this points to an invalid node.
7779 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7781 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7782 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7783 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7784 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7785 ret->alloc(nbOfCells,4);
7786 double *retPtr(ret->getPointer());
7787 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7788 const double *coor(_coords->begin());
7789 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7791 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7792 if(nodalI[1]-nodalI[0]>=3)
7794 for(int j=0;j<3;j++)
7796 int nodeId(nodal[nodalI[0]+1+j]);
7797 if(nodeId>=0 && nodeId<nbOfNodes)
7798 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7801 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7802 throw INTERP_KERNEL::Exception(oss.str().c_str());
7808 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7809 throw INTERP_KERNEL::Exception(oss.str().c_str());
7811 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7812 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7818 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7821 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7825 da->checkAllocated();
7826 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7828 int nbOfTuples=da->getNumberOfTuples();
7829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7831 c->alloc(2*nbOfTuples,1);
7832 cI->alloc(nbOfTuples+1,1);
7833 int *cp=c->getPointer();
7834 int *cip=cI->getPointer();
7836 for(int i=0;i<nbOfTuples;i++)
7838 *cp++=INTERP_KERNEL::NORM_POINT1;
7842 ret->setConnectivity(c,cI,true);
7846 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7847 * Cells and nodes of
7848 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7849 * \param [in] mesh1 - the first mesh.
7850 * \param [in] mesh2 - the second mesh.
7851 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7852 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7853 * is no more needed.
7854 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7855 * \throw If the coordinates array is not set in none of the meshes.
7856 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7857 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7859 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7861 std::vector<const MEDCouplingUMesh *> tmp(2);
7862 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7863 return MergeUMeshes(tmp);
7867 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7868 * Cells and nodes of
7869 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7870 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7871 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7872 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7873 * is no more needed.
7874 * \throw If \a a.size() == 0.
7875 * \throw If \a a[ *i* ] == NULL.
7876 * \throw If the coordinates array is not set in none of the meshes.
7877 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7878 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7880 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7882 std::size_t sz=a.size();
7884 return MergeUMeshesLL(a);
7885 for(std::size_t ii=0;ii<sz;ii++)
7888 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7889 throw INTERP_KERNEL::Exception(oss.str().c_str());
7891 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7892 std::vector< const MEDCouplingUMesh * > aa(sz);
7894 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7896 const MEDCouplingUMesh *cur=a[i];
7897 const DataArrayDouble *coo=cur->getCoords();
7899 spaceDim=coo->getNumberOfComponents();
7902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7903 for(std::size_t i=0;i<sz;i++)
7905 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7908 return MergeUMeshesLL(aa);
7913 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7917 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7918 int meshDim=(*it)->getMeshDimension();
7919 int nbOfCells=(*it)->getNumberOfCells();
7920 int meshLgth=(*it++)->getMeshLength();
7921 for(;it!=a.end();it++)
7923 if(meshDim!=(*it)->getMeshDimension())
7924 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7925 nbOfCells+=(*it)->getNumberOfCells();
7926 meshLgth+=(*it)->getMeshLength();
7928 std::vector<const MEDCouplingPointSet *> aps(a.size());
7929 std::copy(a.begin(),a.end(),aps.begin());
7930 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7931 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7932 ret->setCoords(pts);
7933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7934 c->alloc(meshLgth,1);
7935 int *cPtr=c->getPointer();
7936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7937 cI->alloc(nbOfCells+1,1);
7938 int *cIPtr=cI->getPointer();
7942 for(it=a.begin();it!=a.end();it++)
7944 int curNbOfCell=(*it)->getNumberOfCells();
7945 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7946 const int *curC=(*it)->_nodal_connec->getConstPointer();
7947 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7948 for(int j=0;j<curNbOfCell;j++)
7950 const int *src=curC+curCI[j];
7952 for(;src!=curC+curCI[j+1];src++,cPtr++)
7960 offset+=curCI[curNbOfCell];
7961 offset2+=(*it)->getNumberOfNodes();
7964 ret->setConnectivity(c,cI,true);
7971 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7972 * dimension and sharing the node coordinates array.
7973 * All cells of the first mesh precede all cells of the second mesh
7974 * within the result mesh.
7975 * \param [in] mesh1 - the first mesh.
7976 * \param [in] mesh2 - the second mesh.
7977 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7978 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7979 * is no more needed.
7980 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7981 * \throw If the meshes do not share the node coordinates array.
7982 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7983 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7985 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7987 std::vector<const MEDCouplingUMesh *> tmp(2);
7988 tmp[0]=mesh1; tmp[1]=mesh2;
7989 return MergeUMeshesOnSameCoords(tmp);
7993 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7994 * dimension and sharing the node coordinates array.
7995 * All cells of the *i*-th mesh precede all cells of the
7996 * (*i*+1)-th mesh within the result mesh.
7997 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7998 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7999 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8000 * is no more needed.
8001 * \throw If \a a.size() == 0.
8002 * \throw If \a a[ *i* ] == NULL.
8003 * \throw If the meshes do not share the node coordinates array.
8004 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
8005 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8007 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8010 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8011 for(std::size_t ii=0;ii<meshes.size();ii++)
8014 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8015 throw INTERP_KERNEL::Exception(oss.str().c_str());
8017 const DataArrayDouble *coords=meshes.front()->getCoords();
8018 int meshDim=meshes.front()->getMeshDimension();
8019 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8021 int meshIndexLgth=0;
8022 for(;iter!=meshes.end();iter++)
8024 if(coords!=(*iter)->getCoords())
8025 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8026 if(meshDim!=(*iter)->getMeshDimension())
8027 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8028 meshLgth+=(*iter)->getMeshLength();
8029 meshIndexLgth+=(*iter)->getNumberOfCells();
8031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8032 nodal->alloc(meshLgth,1);
8033 int *nodalPtr=nodal->getPointer();
8034 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8035 nodalIndex->alloc(meshIndexLgth+1,1);
8036 int *nodalIndexPtr=nodalIndex->getPointer();
8038 for(iter=meshes.begin();iter!=meshes.end();iter++)
8040 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8041 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8042 int nbOfCells=(*iter)->getNumberOfCells();
8043 int meshLgth2=(*iter)->getMeshLength();
8044 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8045 if(iter!=meshes.begin())
8046 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8048 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8051 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8052 ret->setName("merge");
8053 ret->setMeshDimension(meshDim);
8054 ret->setConnectivity(nodal,nodalIndex,true);
8055 ret->setCoords(coords);
8060 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8061 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8062 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8063 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8064 * New" mode are returned for each input mesh.
8065 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8066 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8067 * valid values [0,1,2], see zipConnectivityTraducer().
8068 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8069 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8070 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8072 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8073 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8074 * is no more needed.
8075 * \throw If \a meshes.size() == 0.
8076 * \throw If \a meshes[ *i* ] == NULL.
8077 * \throw If the meshes do not share the node coordinates array.
8078 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8079 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8080 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8081 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8083 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8085 //All checks are delegated to MergeUMeshesOnSameCoords
8086 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8088 corr.resize(meshes.size());
8089 std::size_t nbOfMeshes=meshes.size();
8091 const int *o2nPtr=o2n->getConstPointer();
8092 for(std::size_t i=0;i<nbOfMeshes;i++)
8094 DataArrayInt *tmp=DataArrayInt::New();
8095 int curNbOfCells=meshes[i]->getNumberOfCells();
8096 tmp->alloc(curNbOfCells,1);
8097 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8098 offset+=curNbOfCells;
8099 tmp->setName(meshes[i]->getName());
8106 * Makes all given meshes share the nodal connectivity array. The common connectivity
8107 * array is created by concatenating the connectivity arrays of all given meshes. All
8108 * the given meshes must be of the same space dimension but dimension of cells **can
8109 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8110 * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8111 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8112 * \param [in,out] meshes - a vector of meshes to update.
8113 * \throw If any of \a meshes is NULL.
8114 * \throw If the coordinates array is not set in any of \a meshes.
8115 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8116 * \throw If \a meshes are of different space dimension.
8118 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8120 std::size_t sz=meshes.size();
8123 std::vector< const DataArrayDouble * > coords(meshes.size());
8124 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8125 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8129 (*it)->checkConnectivityFullyDefined();
8130 const DataArrayDouble *coo=(*it)->getCoords();
8135 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8136 oss << " has no coordinate array defined !";
8137 throw INTERP_KERNEL::Exception(oss.str().c_str());
8142 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8143 oss << " is null !";
8144 throw INTERP_KERNEL::Exception(oss.str().c_str());
8147 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8148 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8149 int offset=(*it)->getNumberOfNodes();
8150 (*it++)->setCoords(res);
8151 for(;it!=meshes.end();it++)
8153 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8154 (*it)->setCoords(res);
8155 (*it)->shiftNodeNumbersInConn(offset);
8156 offset+=oldNumberOfNodes;
8161 * Merges nodes coincident with a given precision within all given meshes that share
8162 * the nodal connectivity array. The given meshes **can be of different** mesh
8163 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8164 * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8165 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8166 * \param [in,out] meshes - a vector of meshes to update.
8167 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8168 * \throw If any of \a meshes is NULL.
8169 * \throw If the \a meshes do not share the same node coordinates array.
8170 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8172 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8176 std::set<const DataArrayDouble *> s;
8177 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8180 s.insert((*it)->getCoords());
8183 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 !";
8184 throw INTERP_KERNEL::Exception(oss.str().c_str());
8189 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 !";
8190 throw INTERP_KERNEL::Exception(oss.str().c_str());
8192 const DataArrayDouble *coo=*(s.begin());
8196 DataArrayInt *comm,*commI;
8197 coo->findCommonTuples(eps,-1,comm,commI);
8198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8199 int oldNbOfNodes=coo->getNumberOfTuples();
8201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8202 if(oldNbOfNodes==newNbOfNodes)
8204 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8205 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8207 (*it)->renumberNodesInConn(o2n->getConstPointer());
8208 (*it)->setCoords(newCoords);
8213 * 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.
8214 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8215 * \param isQuad specifies the policy of connectivity.
8216 * @ret in/out parameter in which the result will be append
8218 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8220 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8221 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8222 ret.push_back(cm.getExtrudedType());
8223 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8226 case INTERP_KERNEL::NORM_POINT1:
8228 ret.push_back(connBg[1]);
8229 ret.push_back(connBg[1]+nbOfNodesPerLev);
8232 case INTERP_KERNEL::NORM_SEG2:
8234 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8235 ret.insert(ret.end(),conn,conn+4);
8238 case INTERP_KERNEL::NORM_SEG3:
8240 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8241 ret.insert(ret.end(),conn,conn+8);
8244 case INTERP_KERNEL::NORM_QUAD4:
8246 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8247 ret.insert(ret.end(),conn,conn+8);
8250 case INTERP_KERNEL::NORM_TRI3:
8252 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8253 ret.insert(ret.end(),conn,conn+6);
8256 case INTERP_KERNEL::NORM_TRI6:
8258 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,
8259 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8260 ret.insert(ret.end(),conn,conn+15);
8263 case INTERP_KERNEL::NORM_QUAD8:
8266 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8267 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8268 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8270 ret.insert(ret.end(),conn,conn+20);
8273 case INTERP_KERNEL::NORM_POLYGON:
8275 std::back_insert_iterator< std::vector<int> > ii(ret);
8276 std::copy(connBg+1,connEnd,ii);
8278 std::reverse_iterator<const int *> rConnBg(connEnd);
8279 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8280 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8281 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8282 for(std::size_t i=0;i<nbOfRadFaces;i++)
8285 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8286 std::copy(conn,conn+4,ii);
8291 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8296 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8298 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8301 double v[3]={0.,0.,0.};
8302 std::size_t sz=std::distance(begin,end);
8307 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];
8308 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8309 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8311 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8313 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8314 // SEG3 forming a circle):
8315 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8317 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8318 for(std::size_t j=0;j<sz;j++)
8320 if (j%2) // current point i is quadratic, next point i+1 is standard
8323 ip1 = (j+1)%sz; // ip1 = "i+1"
8325 else // current point i is standard, next point i+1 is quadratic
8330 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8331 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8332 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8334 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8340 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8342 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8344 std::vector<std::pair<int,int> > edges;
8345 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8346 const int *bgFace=begin;
8347 for(std::size_t i=0;i<nbOfFaces;i++)
8349 const int *endFace=std::find(bgFace+1,end,-1);
8350 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8351 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8353 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8354 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8356 edges.push_back(p1);
8360 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8364 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8366 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8368 double vec0[3],vec1[3];
8369 std::size_t sz=std::distance(begin,end);
8371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8372 int nbOfNodes=(int)sz/2;
8373 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8374 const double *pt0=coords+3*begin[0];
8375 const double *pt1=coords+3*begin[nbOfNodes];
8376 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8377 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8380 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8382 std::size_t sz=std::distance(begin,end);
8383 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8384 std::size_t nbOfNodes(sz/2);
8385 std::copy(begin,end,(int *)tmp);
8386 for(std::size_t j=1;j<nbOfNodes;j++)
8388 begin[j]=tmp[nbOfNodes-j];
8389 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8393 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8395 std::size_t sz=std::distance(begin,end);
8397 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency1 !");
8398 double vec0[3],vec1[3];
8399 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8400 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];
8401 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;
8404 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8406 std::size_t sz=std::distance(begin,end);
8408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency1 !");
8410 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8411 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8412 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8416 * 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 )
8417 * 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
8420 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8421 * \param [in] coords the coordinates with nb of components exactly equal to 3
8422 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8423 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8424 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8426 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8428 int nbFaces=std::count(begin+1,end,-1)+1;
8429 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8430 double *vPtr=v->getPointer();
8431 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8432 double *pPtr=p->getPointer();
8433 const int *stFaceConn=begin+1;
8434 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8436 const int *endFaceConn=std::find(stFaceConn,end,-1);
8437 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8438 stFaceConn=endFaceConn+1;
8440 pPtr=p->getPointer(); vPtr=v->getPointer();
8441 DataArrayInt *comm1=0,*commI1=0;
8442 v->findCommonTuples(eps,-1,comm1,commI1);
8443 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8444 const int *comm1Ptr=comm1->getConstPointer();
8445 const int *commI1Ptr=commI1->getConstPointer();
8446 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8447 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8449 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8450 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8451 mm->finishInsertingCells();
8453 for(int i=0;i<nbOfGrps1;i++)
8455 int vecId=comm1Ptr[commI1Ptr[i]];
8456 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8457 DataArrayInt *comm2=0,*commI2=0;
8458 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8460 const int *comm2Ptr=comm2->getConstPointer();
8461 const int *commI2Ptr=commI2->getConstPointer();
8462 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8463 for(int j=0;j<nbOfGrps2;j++)
8465 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8467 res->insertAtTheEnd(begin,end);
8468 res->pushBackSilent(-1);
8472 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8474 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8475 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8476 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8477 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8480 const int *idsNodePtr=idsNode->getConstPointer();
8481 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];
8482 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8483 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8484 if(std::abs(norm)>eps)
8486 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8487 mm3->rotate(center,vec,angle);
8489 mm3->changeSpaceDimension(2);
8490 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8491 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8492 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8493 int nbOfCells=mm4->getNumberOfCells();
8494 for(int k=0;k<nbOfCells;k++)
8497 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8498 res->pushBackSilent(idsNodePtr[*work]);
8499 res->pushBackSilent(-1);
8504 res->popBackSilent();
8508 * 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
8509 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8511 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8512 * \param [in] coords coordinates expected to have 3 components.
8513 * \param [in] begin start of the nodal connectivity of the face.
8514 * \param [in] end end of the nodal connectivity (excluded) of the face.
8515 * \param [out] v the normalized vector of size 3
8516 * \param [out] p the pos of plane
8518 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8520 std::size_t nbPoints=std::distance(begin,end);
8522 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8523 double vec[3]={0.,0.,0.};
8525 bool refFound=false;
8526 for(;j<nbPoints-1 && !refFound;j++)
8528 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8529 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8530 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8531 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8535 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8538 for(std::size_t i=j;i<nbPoints-1;i++)
8541 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8542 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8543 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8544 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8547 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8548 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];
8549 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8552 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8553 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8557 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8561 * This method tries to obtain a well oriented polyhedron.
8562 * If the algorithm fails, an exception will be thrown.
8564 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8566 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8567 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8568 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8570 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8571 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8572 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8574 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8577 std::size_t smthChanged=0;
8578 for(std::size_t i=0;i<nbOfFaces;i++)
8580 endFace=std::find(bgFace+1,end,-1);
8581 nbOfEdgesInFace=std::distance(bgFace,endFace);
8585 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8587 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8588 std::pair<int,int> p2(p1.second,p1.first);
8589 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8590 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8591 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8596 std::reverse(bgFace+1,endFace);
8597 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8599 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8600 std::pair<int,int> p2(p1.second,p1.first);
8601 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8602 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8603 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8604 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8605 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8606 if(it!=edgesOK.end())
8609 edgesFinished.push_back(p1);
8612 edgesOK.push_back(p1);
8619 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8621 if(!edgesOK.empty())
8622 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8623 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8624 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8626 for(std::size_t i=0;i<nbOfFaces;i++)
8628 endFace=std::find(bgFace+1,end,-1);
8629 std::reverse(bgFace+1,endFace);
8635 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8637 int nbOfNodesExpected(skin->getNumberOfNodes());
8638 const int *n2oPtr(n2o->getConstPointer());
8639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8640 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8641 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8642 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8643 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8645 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8646 if(nbOfNodesExpected<1)
8648 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8649 *work++=n2oPtr[prevNode];
8650 for(int i=1;i<nbOfNodesExpected;i++)
8652 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8654 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8655 conn.erase(prevNode);
8658 int curNode(*(conn.begin()));
8659 *work++=n2oPtr[curNode];
8660 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8661 shar.erase(prevCell);
8664 prevCell=*(shar.begin());
8668 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8674 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8679 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8681 int nbOfNodesExpected(skin->getNumberOfNodes());
8682 int nbOfTurn(nbOfNodesExpected/2);
8683 const int *n2oPtr(n2o->getConstPointer());
8684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8685 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8686 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8687 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8688 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8690 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8691 if(nbOfNodesExpected<1)
8693 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8694 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8695 for(int i=1;i<nbOfTurn;i++)
8697 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8699 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8700 conn.erase(prevNode);
8703 int curNode(*(conn.begin()));
8704 *work=n2oPtr[curNode];
8705 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8706 shar.erase(prevCell);
8709 int curCell(*(shar.begin()));
8710 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8722 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8728 * This method makes the assumption spacedimension == meshdimension == 2.
8729 * This method works only for linear cells.
8731 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8733 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8735 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8736 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8737 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8738 int oldNbOfNodes(skin->getNumberOfNodes());
8739 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8740 int nbOfNodesExpected(skin->getNumberOfNodes());
8741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8742 int nbCells(skin->getNumberOfCells());
8743 if(nbCells==nbOfNodesExpected)
8744 return buildUnionOf2DMeshLinear(skin,n2o);
8745 else if(2*nbCells==nbOfNodesExpected)
8746 return buildUnionOf2DMeshQuadratic(skin,n2o);
8748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8752 * This method makes the assumption spacedimension == meshdimension == 3.
8753 * This method works only for linear cells.
8755 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8757 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8759 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8760 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8761 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8762 const int *conn=m->getNodalConnectivity()->getConstPointer();
8763 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8764 int nbOfCells=m->getNumberOfCells();
8765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8766 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8769 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8770 for(int i=1;i<nbOfCells;i++)
8773 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8779 * \brief Creates a graph of cell neighbors
8780 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8781 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8783 * - index: 0 3 5 6 6
8784 * - value: 1 2 3 2 3 3
8785 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8786 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8788 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8790 checkConnectivityFullyDefined();
8792 int meshDim = this->getMeshDimension();
8793 MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
8794 MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
8795 this->getReverseNodalConnectivity(revConn,indexr);
8796 const int* indexr_ptr=indexr->getConstPointer();
8797 const int* revConn_ptr=revConn->getConstPointer();
8799 const MEDCoupling::DataArrayInt* index;
8800 const MEDCoupling::DataArrayInt* conn;
8801 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8802 index=this->getNodalConnectivityIndex();
8803 int nbCells=this->getNumberOfCells();
8804 const int* index_ptr=index->getConstPointer();
8805 const int* conn_ptr=conn->getConstPointer();
8807 //creating graph arcs (cell to cell relations)
8808 //arcs are stored in terms of (index,value) notation
8811 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8812 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8814 //warning here one node have less than or equal effective number of cell with it
8815 //but cell could have more than effective nodes
8816 //because other equals nodes in other domain (with other global inode)
8817 std::vector <int> cell2cell_index(nbCells+1,0);
8818 std::vector <int> cell2cell;
8819 cell2cell.reserve(3*nbCells);
8821 for (int icell=0; icell<nbCells;icell++)
8823 std::map<int,int > counter;
8824 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8826 int inode=conn_ptr[iconn];
8827 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8829 int icell2=revConn_ptr[iconnr];
8830 std::map<int,int>::iterator iter=counter.find(icell2);
8831 if (iter!=counter.end()) (iter->second)++;
8832 else counter.insert(std::make_pair(icell2,1));
8835 for (std::map<int,int>::const_iterator iter=counter.begin();
8836 iter!=counter.end(); iter++)
8837 if (iter->second >= meshDim)
8839 cell2cell_index[icell+1]++;
8840 cell2cell.push_back(iter->first);
8845 cell2cell_index[0]=0;
8846 for (int icell=0; icell<nbCells;icell++)
8847 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8849 //filling up index and value to create skylinearray structure
8850 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8855 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8856 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8858 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8862 for(int i=0;i<nbOfNodesInCell;i++)
8863 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8864 else if(spaceDim==2)
8866 for(int i=0;i<nbOfNodesInCell;i++)
8868 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8876 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8878 int nbOfCells=getNumberOfCells();
8880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8881 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};
8882 ofs << " <" << getVTKDataSetType() << ">\n";
8883 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8884 ofs << " <PointData>\n" << pointData << std::endl;
8885 ofs << " </PointData>\n";
8886 ofs << " <CellData>\n" << cellData << std::endl;
8887 ofs << " </CellData>\n";
8888 ofs << " <Points>\n";
8889 if(getSpaceDimension()==3)
8890 _coords->writeVTK(ofs,8,"Points",byteData);
8893 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8894 coo->writeVTK(ofs,8,"Points",byteData);
8896 ofs << " </Points>\n";
8897 ofs << " <Cells>\n";
8898 const int *cPtr=_nodal_connec->getConstPointer();
8899 const int *cIPtr=_nodal_connec_index->getConstPointer();
8900 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8903 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8904 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8905 int szFaceOffsets=0,szConn=0;
8906 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8909 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8912 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8913 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8917 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8918 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8919 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8920 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8921 w4=std::copy(c.begin(),c.end(),w4);
8924 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8925 types->writeVTK(ofs,8,"UInt8","types",byteData);
8926 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8927 if(szFaceOffsets!=0)
8928 {//presence of Polyhedra
8929 connectivity->reAlloc(szConn);
8930 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8931 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8932 w1=faces->getPointer();
8933 for(int i=0;i<nbOfCells;i++)
8934 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8936 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8938 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8939 for(int j=0;j<nbFaces;j++)
8941 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8942 *w1++=(int)std::distance(w6,w5);
8943 w1=std::copy(w6,w5,w1);
8947 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8949 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8950 ofs << " </Cells>\n";
8951 ofs << " </Piece>\n";
8952 ofs << " </" << getVTKDataSetType() << ">\n";
8955 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8957 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8959 { stream << " Not set !"; return ; }
8960 stream << " Mesh dimension : " << _mesh_dim << ".";
8964 { stream << " No coordinates set !"; return ; }
8965 if(!_coords->isAllocated())
8966 { stream << " Coordinates set but not allocated !"; return ; }
8967 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8968 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8969 if(!_nodal_connec_index)
8970 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8971 if(!_nodal_connec_index->isAllocated())
8972 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8973 int lgth=_nodal_connec_index->getNumberOfTuples();
8974 int cpt=_nodal_connec_index->getNumberOfComponents();
8975 if(cpt!=1 || lgth<1)
8977 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8980 std::string MEDCouplingUMesh::getVTKDataSetType() const
8982 return std::string("UnstructuredGrid");
8985 std::string MEDCouplingUMesh::getVTKFileExtension() const
8987 return std::string("vtu");
8991 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8992 * returns a result mesh constituted by polygons.
8993 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8994 * all nodes from m2.
8995 * The meshes should be in 2D space. In
8996 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8998 * \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
8999 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9000 * \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
9001 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9002 * \param [in] eps - precision used to detect coincident mesh entities.
9003 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9004 * cell an id of the cell of \a m1 it comes from. The caller is to delete
9005 * this array using decrRef() as it is no more needed.
9006 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9007 * cell an id of the cell of \a m2 it comes from. -1 value means that a
9008 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9009 * any cell of \a m2. The caller is to delete this array using decrRef() as
9010 * it is no more needed.
9011 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9012 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9013 * is no more needed.
9014 * \throw If the coordinates array is not set in any of the meshes.
9015 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
9016 * \throw If any of the meshes is not a 2D mesh in 2D space.
9018 * \sa conformize2D, mergeNodes
9020 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9021 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9024 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9025 m1->checkFullyDefined();
9026 m2->checkFullyDefined();
9027 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9028 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
9030 // Step 1: compute all edge intersections (new nodes)
9031 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9032 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9033 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9034 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9035 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9036 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9037 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9038 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9039 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9040 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9042 // Step 2: re-order newly created nodes according to the ordering found in m2
9043 std::vector< std::vector<int> > intersectEdge2;
9044 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9045 subDiv2.clear(); dd5=0; dd6=0;
9048 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9049 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9050 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9051 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9053 // Step 4: Prepare final result:
9054 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9055 addCooDa->alloc((int)(addCoo.size())/2,2);
9056 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9057 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9058 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9059 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9060 std::vector<const DataArrayDouble *> coordss(4);
9061 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9062 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9063 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9064 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9066 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9068 ret->setConnectivity(conn,connI,true);
9069 ret->setCoords(coo);
9070 cellNb1=c1.retn(); cellNb2=c2.retn();
9076 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9078 if(candidates.empty())
9080 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9082 const std::vector<int>& pool(intersectEdge1[*it]);
9083 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9084 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9089 tmp[0]=stop; tmp[1]=start;
9090 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9099 MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector<int> >& intersectEdge2, const DataArrayDouble *coords1, const std::vector<double>& addCoo, const std::map<int,int>& mergedNodes, const std::vector< std::vector<int> >& colinear2, const std::vector< std::vector<int> >& intersectEdge1,
9100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9102 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9103 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9104 int nCells(mesh1D->getNumberOfCells());
9105 if(nCells!=(int)intersectEdge2.size())
9106 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9107 const DataArrayDouble *coo2(mesh1D->getCoords());
9108 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9109 const double *coo2Ptr(coo2->begin());
9110 int offset1(coords1->getNumberOfTuples());
9111 int offset2(offset1+coo2->getNumberOfTuples());
9112 int offset3(offset2+addCoo.size()/2);
9113 std::vector<double> addCooQuad;
9114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9115 int tmp[4],cicnt(0),kk(0);
9116 for(int i=0;i<nCells;i++)
9118 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9119 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9120 const std::vector<int>& subEdges(intersectEdge2[i]);
9121 int nbSubEdge(subEdges.size()/2);
9122 for(int j=0;j<nbSubEdge;j++,kk++)
9124 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
9125 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9126 INTERP_KERNEL::Edge *e2Ptr(e2);
9127 std::map<int,int>::const_iterator itm;
9128 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9130 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9131 itm=mergedNodes.find(subEdges[2*j]);
9132 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9133 itm=mergedNodes.find(subEdges[2*j+1]);
9134 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9135 tmp[3]=offset3+(int)addCooQuad.size()/2;
9137 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9139 cOut->insertAtTheEnd(tmp,tmp+4);
9140 ciOut->pushBackSilent(cicnt);
9144 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9145 itm=mergedNodes.find(subEdges[2*j]);
9146 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9147 itm=mergedNodes.find(subEdges[2*j+1]);
9148 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9150 cOut->insertAtTheEnd(tmp,tmp+3);
9151 ciOut->pushBackSilent(cicnt);
9154 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9156 idsInRetColinear->pushBackSilent(kk);
9157 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9162 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9163 ret->setConnectivity(cOut,ciOut,true);
9164 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9165 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9166 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9167 std::vector<const DataArrayDouble *> coordss(4);
9168 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9169 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9170 ret->setCoords(arr);
9174 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9176 std::vector<int> allEdges;
9177 for(const int *it2(descBg);it2!=descEnd;it2++)
9179 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9181 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9183 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9185 std::size_t nb(allEdges.size());
9187 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9188 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9189 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9190 ret->setCoords(coords);
9191 ret->allocateCells(1);
9192 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9193 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9194 connOut[kk]=allEdges[2*kk];
9195 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9199 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9201 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9202 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9204 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9205 if(sz!=std::distance(descBg,descEnd))
9206 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9207 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9208 std::vector<int> allEdges,centers;
9209 const double *coordsPtr(coords->begin());
9210 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9211 int offset(coords->getNumberOfTuples());
9212 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9214 INTERP_KERNEL::NormalizedCellType typeOfSon;
9215 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9216 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9218 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9220 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9222 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9224 {//the current edge has been subsplit -> create corresponding centers.
9225 std::size_t nbOfCentersToAppend(edge1.size()/2);
9226 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9227 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9228 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9229 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9232 const double *aa(coordsPtr+2*(*it3++));
9233 const double *bb(coordsPtr+2*(*it3++));
9234 ee->getMiddleOfPoints(aa,bb,tmpp);
9235 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9236 centers.push_back(offset+k);
9240 std::size_t nb(allEdges.size());
9242 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9243 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9244 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9246 ret->setCoords(coords);
9249 addCoo->rearrange(2);
9250 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9251 ret->setCoords(addCoo);
9253 ret->allocateCells(1);
9254 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9255 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9256 connOut[kk]=allEdges[2*kk];
9257 connOut.insert(connOut.end(),centers.begin(),centers.end());
9258 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9263 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9266 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9268 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9270 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9271 if(!cm.isQuadratic())
9272 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9274 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9277 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9280 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9282 const INTERP_KERNEL::Edge *ee(*it);
9283 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9287 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9290 const double *coo(mesh2D->getCoords()->begin());
9291 std::size_t sz(conn.size());
9292 std::vector<double> addCoo;
9293 std::vector<int> conn2(conn);
9294 int offset(mesh2D->getNumberOfNodes());
9295 for(std::size_t i=0;i<sz;i++)
9298 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9299 addCoo.insert(addCoo.end(),tmp,tmp+2);
9300 conn2.push_back(offset+(int)i);
9302 mesh2D->getCoords()->rearrange(1);
9303 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9304 mesh2D->getCoords()->rearrange(2);
9305 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9310 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9312 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9313 * a set of edges defined in \a splitMesh1D.
9315 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9316 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9318 std::size_t nb(edge1Bis.size()/2);
9319 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9320 int iEnd(splitMesh1D->getNumberOfCells());
9322 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9324 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9325 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9326 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9329 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9330 out0.resize(1); out1.resize(1);
9331 std::vector<int>& connOut(out0[0]);
9332 connOut.resize(nbOfEdgesOf2DCellSplit);
9333 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9334 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9335 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9337 connOut[kk]=edge1Bis[2*kk];
9338 edgesPtr[kk]=edge1BisPtr[2*kk];
9343 // [i,iEnd[ contains the
9344 out0.resize(2); out1.resize(2);
9345 std::vector<int>& connOutLeft(out0[0]);
9346 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9347 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9348 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9349 for(std::size_t k=ii;k<jj+1;k++)
9350 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9351 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9352 for(int ik=0;ik<iEnd;ik++)
9354 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9355 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9358 for(int ik=iEnd-1;ik>=0;ik--)
9359 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9360 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9361 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9362 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9363 for(int ik=0;ik<iEnd;ik++)
9364 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9365 eright.insert(eright.end(),ees.begin(),ees.end());
9377 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9379 std::vector<int> _edges;
9380 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9383 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9385 std::size_t nbe(edges.size());
9386 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9387 for(std::size_t i=0;i<nbe;i++)
9389 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9390 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9392 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9393 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9394 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9400 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9401 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9402 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9403 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9404 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9408 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9409 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9414 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9416 const MEDCouplingUMesh *mesh(_mesh);
9422 { _left++; _right++; return ; }
9425 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9426 if((isLeft && isRight) || (!isLeft && !isRight))
9427 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9438 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9439 if((isLeft && isRight) || (!isLeft && !isRight))
9440 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9455 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9457 const MEDCouplingUMesh *mesh(_mesh);
9460 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9463 {// not fully splitting cell case
9464 if(mesh2D->getNumberOfCells()==1)
9465 {//little optimization. 1 cell no need to find in which cell mesh is !
9466 neighbors[0]=offset; neighbors[1]=offset;
9471 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9472 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9474 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9475 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9480 class VectorOfCellInfo
9483 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9484 std::size_t size() const { return _pool.size(); }
9485 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9486 void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9487 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9488 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9489 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9490 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9492 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9493 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9494 const CellInfo& get(int pos) const;
9495 CellInfo& get(int pos);
9497 std::vector<CellInfo> _pool;
9498 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9499 std::vector<EdgeInfo> _edge_info;
9502 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9504 _pool[0]._edges=edges;
9505 _pool[0]._edges_ptr=edgesPtr;
9508 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9511 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9514 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9516 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9517 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9518 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9521 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9523 get(pos);//to check pos
9524 bool isFast(pos==0 && _pool.size()==1);
9525 std::size_t sz(edges.size());
9526 // dealing with edges
9528 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9530 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9532 std::vector<CellInfo> pool(_pool.size()-1+sz);
9533 for(int i=0;i<pos;i++)
9535 for(std::size_t j=0;j<sz;j++)
9536 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9537 for(int i=pos+1;i<(int)_pool.size();i++)
9538 pool[i+sz-1]=_pool[i];
9542 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9550 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9553 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9557 if(pos<_ze_mesh->getNumberOfCells()-1)
9559 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9562 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9563 for(std::size_t j=0;j<ms2.size();j++)
9565 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9568 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9570 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9573 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9576 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9578 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9580 if((*it).isInMyRange(pos))
9583 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9586 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9588 get(pos);//to check;
9589 if(_edge_info.empty())
9591 std::size_t sz(_edge_info.size()-1);
9592 for(std::size_t i=0;i<sz;i++)
9593 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9596 const CellInfo& VectorOfCellInfo::get(int pos) const
9598 if(pos<0 || pos>=(int)_pool.size())
9599 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9603 CellInfo& VectorOfCellInfo::get(int pos)
9605 if(pos<0 || pos>=(int)_pool.size())
9606 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9612 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9613 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9615 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9617 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9619 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9621 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9622 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9624 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9625 if(nbCellsInSplitMesh1D==0)
9626 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9627 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9628 std::size_t nb(allEdges.size()),jj;
9630 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9631 std::vector<int> edge1Bis(nb*2);
9632 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9633 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9634 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9635 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9636 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9638 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9639 int *idsLeftRightPtr(idsLeftRight->getPointer());
9640 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9641 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9642 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9644 for(;iEnd<nbCellsInSplitMesh1D;)
9646 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9652 if(iEnd<nbCellsInSplitMesh1D)
9655 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9656 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9658 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9659 retTmp->setCoords(splitMesh1D->getCoords());
9660 retTmp->allocateCells();
9662 std::vector< std::vector<int> > out0;
9663 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9665 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9666 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9667 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9668 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9672 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9673 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9674 return pool.getZeMesh().retn();
9677 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9678 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9681 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9683 std::vector<int> allEdges;
9684 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9685 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9687 int edgeId(std::abs(*it)-1);
9688 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9689 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9690 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9692 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9694 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9695 std::size_t sz(edge1.size());
9696 for(std::size_t cnt=0;cnt<sz;cnt++)
9697 allEdgesPtr.push_back(ee);
9700 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9703 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9705 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9706 {//easy case comparison not
9707 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9709 else if(typ1.isQuadratic() && typ2.isQuadratic())
9711 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9714 if(conn1[2]==conn2[2])
9716 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9717 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9721 {//only one is quadratic
9722 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9725 const double *a(0),*bb(0),*be(0);
9726 if(typ1.isQuadratic())
9728 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9732 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9734 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9735 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9741 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9742 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9744 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9746 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9748 if(candidatesIn2DEnd==candidatesIn2DBg)
9749 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9750 const double *coo(mesh2DSplit->getCoords()->begin());
9751 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9752 return *candidatesIn2DBg;
9753 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9755 if(cellIdInMesh1DSplitRelative<0)
9756 cur1D->changeOrientationOfCells();
9757 const int *c1D(cur1D->getNodalConnectivity()->begin());
9758 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9759 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9761 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9762 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9763 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9764 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9765 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9766 for(unsigned it2=0;it2<sz;it2++)
9768 INTERP_KERNEL::NormalizedCellType typeOfSon;
9769 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9770 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9771 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9775 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9781 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9782 * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9783 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9784 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9786 * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9787 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9788 * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9789 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9790 * \param [in] eps - precision used to perform intersections and localization operations.
9791 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9792 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9793 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9794 * So this array has a number of tuples equal to the number of cells of \a splitMesh2D and a number of component equal to 1.
9795 * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9796 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9797 * So this array has a number of tuples equal to the number of cells of \a splitMesh1D and a number of components equal to 2.
9799 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9801 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9803 if(!mesh2D || !mesh1D)
9804 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9805 mesh2D->checkFullyDefined();
9806 mesh1D->checkFullyDefined();
9807 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9808 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9810 // Step 1: compute all edge intersections (new nodes)
9811 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9812 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9813 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9814 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9816 // Build desc connectivity
9817 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9819 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9820 std::map<int,int> mergedNodes;
9821 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9822 // use mergeNodes to fix intersectEdge1
9823 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9825 std::size_t n((*it0).size()/2);
9826 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9827 std::map<int,int>::const_iterator it1;
9828 it1=mergedNodes.find(eltStart);
9829 if(it1!=mergedNodes.end())
9830 (*it0)[0]=(*it1).second;
9831 it1=mergedNodes.find(eltEnd);
9832 if(it1!=mergedNodes.end())
9833 (*it0)[2*n-1]=(*it1).second;
9836 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9837 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9838 // Step 2: re-order newly created nodes according to the ordering found in m2
9839 std::vector< std::vector<int> > intersectEdge2;
9840 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9842 // Step 3: compute splitMesh1D
9843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9845 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9846 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9849 // deal with cells in mesh2D that are not cut but only some of their edges are
9850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9851 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9852 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9854 if(!idsInDesc2DToBeRefined->empty())
9856 DataArrayInt *out0(0),*outi0(0);
9857 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9858 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9860 out0s=out0s->buildUnique();
9864 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9865 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9867 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9869 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9870 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9871 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9872 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9874 if((DataArrayInt *)out0s)
9875 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9876 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9877 // OK all is ready to insert in ret2 mesh
9878 if(!untouchedCells->empty())
9879 {// the most easy part, cells in mesh2D not impacted at all
9880 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9881 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9882 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9884 if((DataArrayInt *)out0s)
9885 {// here dealing with cells in out0s but not in cellsToBeModified
9886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9887 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9888 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9890 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9891 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9893 int offset(ret2->getNumberOfTuples());
9894 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9896 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9897 int kk(0),*ret3ptr(partOfRet3->getPointer());
9898 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9900 int faceId(std::abs(*it)-1);
9901 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9903 int tmp(fewModifiedCells->locateValue(*it2));
9906 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9907 ret3ptr[2*kk]=tmp+offset;
9908 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9909 ret3ptr[2*kk+1]=tmp+offset;
9912 {//the current edge is shared by a 2D cell that will be split just after
9913 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9914 ret3ptr[2*kk]=-(*it2+1);
9915 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9916 ret3ptr[2*kk+1]=-(*it2+1);
9920 m1Desc->setCoords(ret1->getCoords());
9921 ret1NonCol->setCoords(ret1->getCoords());
9922 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9923 if(!outMesh2DSplit.empty())
9925 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9926 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9927 (*itt)->setCoords(da);
9930 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9931 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9934 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9935 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9936 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9937 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9938 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9939 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9940 outMesh2DSplit.push_back(splitOfOneCell);
9941 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9942 ret2->pushBackSilent(*it);
9945 std::size_t nbOfMeshes(outMesh2DSplit.size());
9946 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9947 for(std::size_t i=0;i<nbOfMeshes;i++)
9948 tmp[i]=outMesh2DSplit[i];
9950 ret1->getCoords()->setInfoOnComponents(compNames);
9951 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9952 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9955 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9957 int old2DCellId(-ret3->getIJ(*it,0)-1);
9958 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9959 ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9961 ret3->changeValue(std::numeric_limits<int>::max(),-1);
9964 splitMesh1D=ret1.retn();
9965 splitMesh2D=ret2D.retn();
9966 cellIdInMesh2D=ret2.retn();
9967 cellIdInMesh1D=ret3.retn();
9971 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9972 * (newly created) nodes corresponding to the edge intersections.
9974 * @param[out] cr, crI connectivity of the resulting mesh
9975 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9976 * TODO: describe input parameters
9978 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9979 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9980 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9981 const std::vector<double>& addCoords,
9982 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9984 static const int SPACEDIM=2;
9985 const double *coo1(m1->getCoords()->getConstPointer());
9986 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9987 int offset1(m1->getNumberOfNodes());
9988 const double *coo2(m2->getCoords()->getConstPointer());
9989 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9990 int offset2(offset1+m2->getNumberOfNodes());
9991 int offset3(offset2+((int)addCoords.size())/2);
9992 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9993 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9994 // Here a BBTree on 2D-cells, not on segments:
9995 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9996 int ncell1(m1->getNumberOfCells());
9998 for(int i=0;i<ncell1;i++)
10000 std::vector<int> candidates2;
10001 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10002 std::map<INTERP_KERNEL::Node *,int> mapp;
10003 std::map<int,INTERP_KERNEL::Node *> mappRev;
10004 INTERP_KERNEL::QuadraticPolygon pol1;
10005 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10006 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10007 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10008 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10009 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10010 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10011 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10013 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
10014 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10015 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10016 for(it1.first();!it1.finished();it1.next())
10017 edges1.insert(it1.current()->getPtr());
10019 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10020 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10022 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10024 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10025 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10026 // Complete mapping with elements coming from the current cell it2 in mesh2:
10027 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10028 // pol2 is the new QP in the final merged result.
10029 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10030 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10033 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10035 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10036 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10037 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10038 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10040 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10041 // by m2 but that we still want to keep in the final result.
10042 if(!edges1.empty())
10046 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10048 catch(INTERP_KERNEL::Exception& e)
10050 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();
10051 throw INTERP_KERNEL::Exception(oss.str().c_str());
10054 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10055 (*it).second->decrRef();
10060 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10061 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10062 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10063 * The caller is to deal with the resulting DataArrayInt.
10064 * \throw If the coordinate array is not set.
10065 * \throw If the nodal connectivity of the cells is not defined.
10066 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10067 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10069 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10071 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10073 checkFullyDefined();
10074 if(getMeshDimension()!=1)
10075 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10077 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10078 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10080 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10081 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10082 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10084 const int * dsi(_dsi->getConstPointer());
10085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10087 if (dsii->getNumberOfTuples())
10088 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10090 int nc(getNumberOfCells());
10091 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10092 result->alloc(nc,1);
10094 // set of edges not used so far
10095 std::set<int> edgeSet;
10096 for (int i=0; i<nc; edgeSet.insert(i), i++);
10100 // while we have points with only one neighbor segments
10103 std::list<int> linePiece;
10104 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10105 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10107 // Fill the list forward (resp. backward) from the start segment:
10108 int activeSeg = startSeg;
10109 int prevPointId = -20;
10111 while (!edgeSet.empty())
10113 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10116 linePiece.push_back(activeSeg);
10118 linePiece.push_front(activeSeg);
10119 edgeSet.erase(activeSeg);
10122 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10123 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10124 if (dsi[ptId] == 1) // hitting the end of the line
10126 prevPointId = ptId;
10127 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10128 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10131 // Done, save final piece into DA:
10132 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10133 newIdx += linePiece.size();
10135 // identify next valid start segment (one which is not consumed)
10136 if(!edgeSet.empty())
10137 startSeg = *(edgeSet.begin());
10139 while (!edgeSet.empty());
10140 return result.retn();
10145 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10147 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10148 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10150 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10151 int v((*it).second);
10152 if(v==forbVal0 || v==forbVal1)
10154 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10155 isect.push_back(v);
10158 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10163 bool presenceOfOn(false);
10164 for(int i=0;i<sz;i++)
10166 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10167 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10169 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10170 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10172 return presenceOfOn;
10178 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10179 * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10180 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10181 * a minimal creation of new nodes is wanted.
10182 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10183 * nodes if a SEG3 is split without information of middle.
10184 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10185 * avoid to have a non conform mesh.
10187 * \return int - the number of new nodes created (in most of cases 0).
10189 * \throw If \a this is not coherent.
10190 * \throw If \a this has not spaceDim equal to 2.
10191 * \throw If \a this has not meshDim equal to 2.
10192 * \throw If some subcells needed to be split are orphan.
10193 * \sa MEDCouplingUMesh::conformize2D
10195 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10197 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10198 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10199 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10200 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10201 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10202 if(midOpt==0 && midOptI==0)
10204 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10207 else if(midOpt!=0 && midOptI!=0)
10208 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10210 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10214 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10215 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10216 * 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
10217 * 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).
10218 * 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.
10220 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10221 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10223 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10224 * This method expects that all nodes in \a this are not closer than \a eps.
10225 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10227 * \param [in] eps the relative error to detect merged edges.
10228 * \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
10229 * that the user is expected to deal with.
10231 * \throw If \a this is not coherent.
10232 * \throw If \a this has not spaceDim equal to 2.
10233 * \throw If \a this has not meshDim equal to 2.
10234 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10236 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10238 static const int SPACEDIM=2;
10240 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10241 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10243 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10244 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10245 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10246 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10247 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10248 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10249 std::vector<double> addCoo;
10250 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10251 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10252 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10253 for(int i=0;i<nDescCell;i++)
10255 std::vector<int> candidates;
10256 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10257 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10260 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10261 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10262 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10263 INTERP_KERNEL::MergePoints merge;
10264 INTERP_KERNEL::QuadraticPolygon c1,c2;
10265 e1->intersectWith(e2,merge,c1,c2);
10266 e1->decrRef(); e2->decrRef();
10267 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10268 overlapEdge[i].push_back(*it);
10269 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10270 overlapEdge[*it].push_back(i);
10273 // splitting done. sort intersect point in intersectEdge.
10274 std::vector< std::vector<int> > middle(nDescCell);
10275 int nbOf2DCellsToBeSplit(0);
10276 bool middleNeedsToBeUsed(false);
10277 std::vector<bool> cells2DToTreat(nDescCell,false);
10278 for(int i=0;i<nDescCell;i++)
10280 std::vector<int>& isect(intersectEdge[i]);
10281 int sz((int)isect.size());
10284 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10285 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10286 e->sortSubNodesAbs(coords,isect);
10291 int idx0(rdi[i]),idx1(rdi[i+1]);
10293 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10294 if(!cells2DToTreat[rd[idx0]])
10296 cells2DToTreat[rd[idx0]]=true;
10297 nbOf2DCellsToBeSplit++;
10299 // try to reuse at most eventual 'middle' of SEG3
10300 std::vector<int>& mid(middle[i]);
10301 mid.resize(sz+1,-1);
10302 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10304 middleNeedsToBeUsed=true;
10305 const std::vector<int>& candidates(overlapEdge[i]);
10306 std::vector<int> trueCandidates;
10307 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10308 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10309 trueCandidates.push_back(*itc);
10310 int stNode(c[ci[i]+1]),endNode(isect[0]);
10311 for(int j=0;j<sz+1;j++)
10313 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10315 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10316 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10317 { mid[j]=*itc; break; }
10320 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10326 if(nbOf2DCellsToBeSplit==0)
10329 int *retPtr(ret->getPointer());
10330 for(int i=0;i<nCell;i++)
10331 if(cells2DToTreat[i])
10334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10335 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10336 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10337 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10338 if(middleNeedsToBeUsed)
10339 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10340 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10341 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10342 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.
10343 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10345 bool areNodesMerged; int newNbOfNodes;
10346 if(nbOfNodesCreated!=0)
10347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10353 * 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.
10354 * 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).
10355 * 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
10356 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10357 * 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
10358 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10360 * 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
10361 * using new instance, idem for coordinates.
10363 * 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.
10365 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10367 * \throw If \a this is not coherent.
10368 * \throw If \a this has not spaceDim equal to 2.
10369 * \throw If \a this has not meshDim equal to 2.
10371 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10373 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10377 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10378 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10379 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10380 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10381 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10382 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10384 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10385 const double *coords(_coords->begin());
10386 int *newciptr(newci->getPointer());
10387 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10389 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10390 ret->pushBackSilent(i);
10391 newciptr[1]=newc->getNumberOfTuples();
10396 if(!appendedCoords->empty())
10398 appendedCoords->rearrange(2);
10399 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10401 setCoords(newCoords);
10404 setConnectivity(newc,newci,true);
10409 * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop.
10410 * So for all edge \a i in \a m1Desc \a intersectEdge1[i] is of length 2*n where n is the number of sub edges.
10411 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10412 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10413 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10414 * \param [out] addCoo - nodes to be append at the end
10415 * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc.
10417 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10418 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2, std::vector<double>& addCoo, std::map<int,int>& mergedNodes)
10420 static const int SPACEDIM=2;
10421 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10422 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10423 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10424 // Build BB tree of all edges in the tool mesh (second mesh)
10425 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10426 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10427 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10428 intersectEdge1.resize(nDescCell1);
10429 colinear2.resize(nDescCell2);
10430 subDiv2.resize(nDescCell2);
10431 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10433 std::vector<int> candidates1(1);
10434 int offset1(m1Desc->getNumberOfNodes());
10435 int offset2(offset1+m2Desc->getNumberOfNodes());
10436 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10438 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10439 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10440 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10442 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10443 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10444 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10446 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10447 // 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
10448 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10449 std::set<INTERP_KERNEL::Node *> nodes;
10450 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10451 std::size_t szz(nodes.size());
10452 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10453 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10454 for(std::size_t iii=0;iii<szz;iii++,itt++)
10455 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10456 // end of protection
10457 // Performs egde cutting:
10458 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10463 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10464 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10469 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10470 * It builds the descending connectivity of the two meshes, and then using a binary tree
10471 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10472 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10474 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10475 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10476 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10477 std::vector<double>& addCoo,
10478 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10480 // Build desc connectivity
10481 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10482 desc2=DataArrayInt::New();
10483 descIndx2=DataArrayInt::New();
10484 revDesc2=DataArrayInt::New();
10485 revDescIndx2=DataArrayInt::New();
10486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10487 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10488 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10489 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10490 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10491 std::map<int,int> notUsedMap;
10492 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10493 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10494 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10498 * This method performs the 2nd step of Partition of 2D mesh.
10499 * This method has 4 inputs :
10500 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10501 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10502 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10503 * 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'
10504 * Nodes end up lying consecutively on a cutted edge.
10505 * \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.
10506 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10507 * \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.
10508 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10509 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10511 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10512 const std::vector<double>& addCoo,
10513 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10515 int offset1=m1->getNumberOfNodes();
10516 int ncell=m2->getNumberOfCells();
10517 const int *c=m2->getNodalConnectivity()->getConstPointer();
10518 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10519 const double *coo=m2->getCoords()->getConstPointer();
10520 const double *cooBis=m1->getCoords()->getConstPointer();
10521 int offset2=offset1+m2->getNumberOfNodes();
10522 intersectEdge.resize(ncell);
10523 for(int i=0;i<ncell;i++,cI++)
10525 const std::vector<int>& divs=subDiv[i];
10526 int nnode=cI[1]-cI[0]-1;
10527 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10528 std::map<INTERP_KERNEL::Node *, int> mapp22;
10529 for(int j=0;j<nnode;j++)
10531 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10532 int nnid=c[(*cI)+j+1];
10533 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10534 mapp22[nn]=nnid+offset1;
10536 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10537 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10538 ((*it).second.first)->decrRef();
10539 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10540 std::map<INTERP_KERNEL::Node *,int> mapp3;
10541 for(std::size_t j=0;j<divs.size();j++)
10544 INTERP_KERNEL::Node *tmp=0;
10546 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10547 else if(id<offset2)
10548 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10550 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10554 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10555 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10562 * 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).
10563 * 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
10564 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10565 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10566 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10567 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10568 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10569 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10570 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10571 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10572 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10573 * \param [out] cut3DSuf input/output param.
10575 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10576 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10577 const int *desc, const int *descIndx,
10578 std::vector< std::pair<int,int> >& cut3DSurf)
10580 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10581 int nbOf3DSurfCell=(int)cut3DSurf.size();
10582 for(int i=0;i<nbOf3DSurfCell;i++)
10584 std::vector<int> res;
10585 int offset=descIndx[i];
10586 int nbOfSeg=descIndx[i+1]-offset;
10587 for(int j=0;j<nbOfSeg;j++)
10589 int edgeId=desc[offset+j];
10590 int status=cut3DCurve[edgeId];
10594 res.push_back(status);
10597 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10598 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10606 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10612 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10613 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10616 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10620 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10625 {// case when plane is on a multi colinear edge of a polyhedron
10626 if((int)res.size()==2*nbOfSeg)
10628 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10638 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10639 * 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).
10640 * 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
10641 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10642 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10643 * \param desc is the descending connectivity 3D->3DSurf
10644 * \param descIndx is the descending connectivity index 3D->3DSurf
10646 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10647 const int *desc, const int *descIndx,
10648 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10650 checkFullyDefined();
10651 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10653 const int *nodal3D=_nodal_connec->getConstPointer();
10654 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10655 int nbOfCells=getNumberOfCells();
10656 for(int i=0;i<nbOfCells;i++)
10658 std::map<int, std::set<int> > m;
10659 int offset=descIndx[i];
10660 int nbOfFaces=descIndx[i+1]-offset;
10663 for(int j=0;j<nbOfFaces;j++)
10665 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10666 if(p.first!=-1 && p.second!=-1)
10670 start=p.first; end=p.second;
10671 m[p.first].insert(p.second);
10672 m[p.second].insert(p.first);
10676 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10677 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10678 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10679 INTERP_KERNEL::NormalizedCellType cmsId;
10680 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10681 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10682 for(unsigned k=0;k<nbOfNodesSon;k++)
10684 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10685 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10692 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10696 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10697 const std::set<int>& s=(*it).second;
10698 std::set<int> s2; s2.insert(prev);
10700 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10703 int val=*s3.begin();
10704 conn.push_back(start);
10711 conn.push_back(end);
10714 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10715 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10716 cellIds->pushBackSilent(i);
10722 * 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
10723 * 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
10724 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10725 * 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
10726 * 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.
10728 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10730 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10732 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10735 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10736 if(cm.getDimension()==2)
10738 const int *node=nodalConnBg+1;
10739 int startNode=*node++;
10740 double refX=coords[2*startNode];
10741 for(;node!=nodalConnEnd;node++)
10743 if(coords[2*(*node)]<refX)
10746 refX=coords[2*startNode];
10749 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10753 double angle0=-M_PI/2;
10758 double angleNext=0.;
10759 while(nextNode!=startNode)
10763 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10765 if(*node!=tmpOut.back() && *node!=prevNode)
10767 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10768 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10773 res=angle0-angleM+2.*M_PI;
10782 if(nextNode!=startNode)
10784 angle0=angleNext-M_PI;
10787 prevNode=tmpOut.back();
10788 tmpOut.push_back(nextNode);
10791 std::vector<int> tmp3(2*(sz-1));
10792 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10793 std::copy(nodalConnBg+1,nodalConnEnd,it);
10794 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10796 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10799 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10801 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10806 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10807 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10812 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10815 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10819 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10820 * 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.
10822 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10823 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10824 * \param [in,out] arr array in which the remove operation will be done.
10825 * \param [in,out] arrIndx array in the remove operation will modify
10826 * \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])
10827 * \return true if \b arr and \b arrIndx have been modified, false if not.
10829 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10831 if(!arrIndx || !arr)
10832 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10833 if(offsetForRemoval<0)
10834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10835 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10836 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10837 int *arrIPtr=arrIndx->getPointer();
10839 int previousArrI=0;
10840 const int *arrPtr=arr->getConstPointer();
10841 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10842 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10844 if(*arrIPtr-previousArrI>offsetForRemoval)
10846 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10848 if(s.find(*work)==s.end())
10849 arrOut.push_back(*work);
10852 previousArrI=*arrIPtr;
10853 *arrIPtr=(int)arrOut.size();
10855 if(arr->getNumberOfTuples()==(int)arrOut.size())
10857 arr->alloc((int)arrOut.size(),1);
10858 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10863 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10864 * (\ref numbering-indirect).
10865 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10866 * The selection of extraction is done standardly in new2old format.
10867 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10869 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10870 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10871 * \param [in] arrIn arr origin array from which the extraction will be done.
10872 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10873 * \param [out] arrOut the resulting array
10874 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10875 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10877 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10878 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10880 if(!arrIn || !arrIndxIn)
10881 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10882 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10883 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10884 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10885 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10886 const int *arrInPtr=arrIn->getConstPointer();
10887 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10888 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10890 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10891 int maxSizeOfArr=arrIn->getNumberOfTuples();
10892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10894 arrIo->alloc((int)(sz+1),1);
10895 const int *idsIt=idsOfSelectBg;
10896 int *work=arrIo->getPointer();
10899 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10901 if(*idsIt>=0 && *idsIt<nbOfGrps)
10902 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10905 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10906 throw INTERP_KERNEL::Exception(oss.str().c_str());
10912 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10913 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10914 throw INTERP_KERNEL::Exception(oss.str().c_str());
10917 arro->alloc(lgth,1);
10918 work=arro->getPointer();
10919 idsIt=idsOfSelectBg;
10920 for(std::size_t i=0;i<sz;i++,idsIt++)
10922 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10923 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10926 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10927 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10928 throw INTERP_KERNEL::Exception(oss.str().c_str());
10931 arrOut=arro.retn();
10932 arrIndexOut=arrIo.retn();
10936 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10937 * (\ref numbering-indirect).
10938 * 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 ).
10939 * The selection of extraction is done standardly in new2old format.
10940 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10942 * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10943 * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10944 * \param [in] idsOfSelectStep
10945 * \param [in] arrIn arr origin array from which the extraction will be done.
10946 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10947 * \param [out] arrOut the resulting array
10948 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10949 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10951 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10952 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10954 if(!arrIn || !arrIndxIn)
10955 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10956 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10957 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10958 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10959 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10960 const int *arrInPtr=arrIn->getConstPointer();
10961 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10962 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10964 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10965 int maxSizeOfArr=arrIn->getNumberOfTuples();
10966 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10967 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10968 arrIo->alloc((int)(sz+1),1);
10969 int idsIt=idsOfSelectStart;
10970 int *work=arrIo->getPointer();
10973 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10975 if(idsIt>=0 && idsIt<nbOfGrps)
10976 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10979 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10980 throw INTERP_KERNEL::Exception(oss.str().c_str());
10986 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10987 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10988 throw INTERP_KERNEL::Exception(oss.str().c_str());
10991 arro->alloc(lgth,1);
10992 work=arro->getPointer();
10993 idsIt=idsOfSelectStart;
10994 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10996 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10997 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11000 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11001 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11002 throw INTERP_KERNEL::Exception(oss.str().c_str());
11005 arrOut=arro.retn();
11006 arrIndexOut=arrIo.retn();
11010 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11011 * 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
11012 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11013 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11015 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11016 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11017 * \param [in] arrIn arr origin array from which the extraction will be done.
11018 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11019 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11020 * \param [in] srcArrIndex index array of \b srcArr
11021 * \param [out] arrOut the resulting array
11022 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11024 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11026 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11027 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11028 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11030 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11031 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11032 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11033 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11034 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11035 std::vector<bool> v(nbOfTuples,true);
11037 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11038 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11039 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11041 if(*it>=0 && *it<nbOfTuples)
11044 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11048 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11049 throw INTERP_KERNEL::Exception(oss.str().c_str());
11052 srcArrIndexPtr=srcArrIndex->getConstPointer();
11053 arrIo->alloc(nbOfTuples+1,1);
11054 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11055 const int *arrInPtr=arrIn->getConstPointer();
11056 const int *srcArrPtr=srcArr->getConstPointer();
11057 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11058 int *arroPtr=arro->getPointer();
11059 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11063 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11064 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11068 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11069 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11070 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11073 arrOut=arro.retn();
11074 arrIndexOut=arrIo.retn();
11078 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11079 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11081 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11082 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11083 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11084 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11085 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11086 * \param [in] srcArrIndex index array of \b srcArr
11088 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11090 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11091 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11093 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11094 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11095 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11096 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11097 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11098 int *arrInOutPtr=arrInOut->getPointer();
11099 const int *srcArrPtr=srcArr->getConstPointer();
11100 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11102 if(*it>=0 && *it<nbOfTuples)
11104 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11105 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11108 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] !";
11109 throw INTERP_KERNEL::Exception(oss.str().c_str());
11114 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11115 throw INTERP_KERNEL::Exception(oss.str().c_str());
11121 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11122 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11123 * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11124 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11125 * A negative value in \b arrIn means that it is ignored.
11126 * 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.
11128 * \param [in] arrIn arr origin array from which the extraction will be done.
11129 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11130 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11131 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11133 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11135 int seed=0,nbOfDepthPeelingPerformed=0;
11136 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11140 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11141 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11142 * 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]].
11143 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11144 * A negative value in \b arrIn means that it is ignored.
11145 * 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.
11146 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11147 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11148 * \param [in] arrIn arr origin array from which the extraction will be done.
11149 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11150 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11151 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11152 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11153 * \sa MEDCouplingUMesh::partitionBySpreadZone
11155 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11157 nbOfDepthPeelingPerformed=0;
11159 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11160 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11163 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11167 std::vector<bool> fetched(nbOfTuples,false);
11168 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11171 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11173 nbOfDepthPeelingPerformed=0;
11174 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11175 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11176 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11177 std::vector<bool> fetched2(nbOfTuples,false);
11179 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11181 if(*seedElt>=0 && *seedElt<nbOfTuples)
11182 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11184 { 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()); }
11186 const int *arrInPtr=arrIn->getConstPointer();
11187 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11188 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11189 std::vector<int> idsToFetch1(seedBg,seedEnd);
11190 std::vector<int> idsToFetch2;
11191 std::vector<int> *idsToFetch=&idsToFetch1;
11192 std::vector<int> *idsToFetchOther=&idsToFetch2;
11193 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11195 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11196 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11198 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11199 std::swap(idsToFetch,idsToFetchOther);
11200 idsToFetchOther->clear();
11201 nbOfDepthPeelingPerformed++;
11203 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11206 int *retPtr=ret->getPointer();
11207 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11214 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11215 * 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
11216 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11217 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11219 * \param [in] start begin of set of ids of the input extraction (included)
11220 * \param [in] end end of set of ids of the input extraction (excluded)
11221 * \param [in] step step of the set of ids in range mode.
11222 * \param [in] arrIn arr origin array from which the extraction will be done.
11223 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11224 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11225 * \param [in] srcArrIndex index array of \b srcArr
11226 * \param [out] arrOut the resulting array
11227 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11229 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11231 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11232 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11233 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11235 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11236 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11239 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11241 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11242 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11243 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11245 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11247 if(it>=0 && it<nbOfTuples)
11248 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11251 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11252 throw INTERP_KERNEL::Exception(oss.str().c_str());
11255 srcArrIndexPtr=srcArrIndex->getConstPointer();
11256 arrIo->alloc(nbOfTuples+1,1);
11257 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11258 const int *arrInPtr=arrIn->getConstPointer();
11259 const int *srcArrPtr=srcArr->getConstPointer();
11260 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11261 int *arroPtr=arro->getPointer();
11262 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11264 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11267 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11268 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11272 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11273 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11276 arrOut=arro.retn();
11277 arrIndexOut=arrIo.retn();
11281 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11282 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11284 * \param [in] start begin of set of ids of the input extraction (included)
11285 * \param [in] end end of set of ids of the input extraction (excluded)
11286 * \param [in] step step of the set of ids in range mode.
11287 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11288 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11289 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11290 * \param [in] srcArrIndex index array of \b srcArr
11292 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11294 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11295 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11297 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11298 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11299 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11300 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11301 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11302 int *arrInOutPtr=arrInOut->getPointer();
11303 const int *srcArrPtr=srcArr->getConstPointer();
11304 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11306 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11308 if(it>=0 && it<nbOfTuples)
11310 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11311 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11314 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11315 throw INTERP_KERNEL::Exception(oss.str().c_str());
11320 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11321 throw INTERP_KERNEL::Exception(oss.str().c_str());
11327 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11328 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11329 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11330 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11331 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11333 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11335 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11337 checkFullyDefined();
11338 int mdim=getMeshDimension();
11339 int spaceDim=getSpaceDimension();
11341 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11342 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11343 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11344 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11346 ret->setCoords(getCoords());
11347 ret->allocateCells((int)partition.size());
11349 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11351 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11356 cell=tmp->buildUnionOf2DMesh();
11359 cell=tmp->buildUnionOf3DMesh();
11362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11365 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11368 ret->finishInsertingCells();
11373 * This method partitions \b this into contiguous zone.
11374 * This method only needs a well defined connectivity. Coordinates are not considered here.
11375 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11377 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11379 int nbOfCellsCur=getNumberOfCells();
11380 std::vector<DataArrayInt *> ret;
11381 if(nbOfCellsCur<=0)
11383 DataArrayInt *neigh=0,*neighI=0;
11384 computeNeighborsOfCells(neigh,neighI);
11385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11386 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11387 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11389 while(seed<nbOfCellsCur)
11391 int nbOfPeelPerformed=0;
11392 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11393 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11395 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11396 ret.push_back((*it).retn());
11401 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11402 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11404 * \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.
11405 * \return a newly allocated DataArrayInt to be managed by the caller.
11406 * \throw In case of \a code has not the right format (typically of size 3*n)
11408 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11410 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11411 std::size_t nb=code.size()/3;
11412 if(code.size()%3!=0)
11413 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11414 ret->alloc((int)nb,2);
11415 int *retPtr=ret->getPointer();
11416 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11418 retPtr[0]=code[3*i+2];
11419 retPtr[1]=code[3*i+2]+code[3*i+1];
11425 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11426 * All cells in \a this are expected to be linear 3D cells.
11427 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11428 * It leads to an increase to number of cells.
11429 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11430 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11431 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11433 * \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.
11434 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11435 * \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.
11436 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11437 * an id of old cell producing it. The caller is to delete this array using
11438 * decrRef() as it is no more needed.
11439 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11441 * \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
11442 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11444 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11445 * \throw If \a this is not fully constituted with linear 3D cells.
11446 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11448 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11450 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11451 checkConnectivityFullyDefined();
11452 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11454 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11455 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11457 int *retPt(ret->getPointer());
11458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11459 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11460 const int *oldc(_nodal_connec->begin());
11461 const int *oldci(_nodal_connec_index->begin());
11462 const double *coords(_coords->begin());
11463 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11465 std::vector<int> a; std::vector<double> b;
11466 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11467 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11468 const int *aa(&a[0]);
11471 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11473 *it=(-(*(it))-1+nbNodes);
11474 addPts->insertAtTheEnd(b.begin(),b.end());
11475 nbNodes+=(int)b.size()/3;
11477 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11478 newConn->insertAtTheEnd(aa,aa+4);
11480 if(!addPts->empty())
11482 addPts->rearrange(3);
11483 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11484 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11485 ret0->setCoords(addPts);
11489 nbOfAdditionalPoints=0;
11490 ret0->setCoords(getCoords());
11492 ret0->setNodalConnectivity(newConn);
11494 ret->computeOffsets2();
11495 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11496 return ret0.retn();
11500 * 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).
11502 * \sa MEDCouplingUMesh::split2DCells
11504 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11506 checkConnectivityFullyDefined();
11507 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11509 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11510 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11511 int prevPosOfCi(ciPtr[0]);
11512 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11514 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11515 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11516 for(int j=0;j<sz;j++)
11518 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11519 for(int k=0;k<sz2;k++)
11520 *cPtr++=subPtr[offset2+k];
11522 *cPtr++=oldConn[prevPosOfCi+j+2];
11525 prevPosOfCi=ciPtr[1];
11526 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11529 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11530 _nodal_connec->decrRef();
11531 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11534 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11540 int ret(nodesCnter++);
11542 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11543 addCoo.insertAtTheEnd(newPt,newPt+2);
11548 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11554 int ret(nodesCnter++);
11556 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11557 addCoo.insertAtTheEnd(newPt,newPt+2);
11565 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)
11568 int trueStart(start>=0?start:nbOfEdges+start);
11569 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11570 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11575 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11576 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11577 middles.push_back(tmp3+offset);
11580 middles.push_back(connBg[trueStart+nbOfEdges]);
11584 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)
11586 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11587 newConnOfCell->pushBackSilent(tmpEnd);
11592 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11593 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11594 middles.push_back(tmp3+offset);
11597 middles.push_back(connBg[start+nbOfEdges]);
11601 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)
11603 // only the quadratic point to deal with:
11608 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11609 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11610 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11611 middles.push_back(tmp3+offset);
11614 middles.push_back(connBg[start+nbOfEdges]);
11621 * 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 ) .
11622 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11624 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11626 std::size_t sz(std::distance(connBg,connEnd));
11627 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11630 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11631 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11632 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11633 unsigned nbOfHit(0); // number of fusions operated
11634 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11635 const unsigned int maxNbOfHit = cm.isQuadratic() ? nbs-2 : nbs-3; // a quad cell is authorized to end up with only two edges, a linear one has to keep 3 at least
11636 INTERP_KERNEL::NormalizedCellType typeOfSon;
11637 std::vector<int> middles;
11639 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11641 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11642 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11643 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11644 posEndElt = posBaseElt+1;
11646 // Look backward first: are the final edges of the cells colinear with the first ones?
11647 // This initializes posBaseElt.
11650 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11652 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11653 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11654 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11655 bool isColinear=eint->areColinears();
11668 // Now move forward:
11669 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11670 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11672 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11673 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11674 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11675 bool isColinear(eint->areColinears());
11687 //push [posBaseElt,posEndElt) in newConnOfCell using e
11688 // The if clauses below are (volontary) not mutually exclusive: on a quad cell with 2 edges, the end of the connectivity is also its begining!
11690 // at the begining of the connectivity (insert type)
11691 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11692 else if((nbOfHit+nbOfTurn) != (nbs-1))
11694 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11695 if ((nbOfHit+nbOfTurn) == (nbs-1))
11696 // at the end (only quad points to deal with)
11697 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11698 posBaseElt=posEndElt;
11701 if(!middles.empty())
11702 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11707 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11709 * \return int - the number of new nodes created.
11710 * \sa MEDCouplingUMesh::split2DCells
11712 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11715 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11717 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11718 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11719 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11720 const double *oldCoordsPtr(getCoords()->begin());
11721 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11722 int prevPosOfCi(ciPtr[0]);
11723 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11725 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11726 for(int j=0;j<sz;j++)
11727 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11728 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11729 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11731 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11735 cPtr[1]=oldConn[prevPosOfCi+2+j];
11736 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11739 std::vector<INTERP_KERNEL::Node *> ns(3);
11740 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11741 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11742 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11743 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11744 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11746 cPtr[1]=subPtr[offset2+k];
11747 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11749 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11751 { cPtr[1]=tmpEnd; }
11752 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11754 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11755 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11759 _nodal_connec->decrRef();
11760 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11761 addCoo->rearrange(2);
11762 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11764 return addCoo->getNumberOfTuples();
11767 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11769 if(nodalConnec && nodalConnecIndex)
11772 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11773 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11775 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11776 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11780 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11781 _own_cell(true),_cell_id(-1),_nb_cell(0)
11786 _nb_cell=mesh->getNumberOfCells();
11790 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11798 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11799 _own_cell(false),_cell_id(bg-1),
11806 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11809 if(_cell_id<_nb_cell)
11818 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11824 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11826 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11829 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11835 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11843 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11849 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11854 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11859 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11861 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11864 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11869 _nb_cell=mesh->getNumberOfCells();
11873 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11880 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11882 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11883 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11884 if(_cell_id<_nb_cell)
11886 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11887 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
11888 int startId=_cell_id;
11889 _cell_id+=nbOfElems;
11890 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11896 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11900 _conn=mesh->getNodalConnectivity()->getPointer();
11901 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11905 void MEDCouplingUMeshCell::next()
11907 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11912 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11915 std::string MEDCouplingUMeshCell::repr() const
11917 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11919 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11921 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11925 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11928 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11930 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11931 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11933 return INTERP_KERNEL::NORM_ERROR;
11936 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11939 if(_conn_lgth!=NOTICABLE_FIRST_VAL)