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 ParaMEDMEM;
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
56 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 };
58 MEDCouplingUMesh *MEDCouplingUMesh::New()
60 return new MEDCouplingUMesh;
63 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
65 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
66 ret->setName(meshName);
67 ret->setMeshDimension(meshDim);
72 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
73 * between \a this and the new mesh.
74 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
75 * delete this mesh using decrRef() as it is no more needed.
77 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
83 * Returns a new MEDCouplingMesh which is a copy of \a this one.
84 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
85 * this mesh are shared by the new mesh.
86 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
87 * delete this mesh using decrRef() as it is no more needed.
89 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
91 return new MEDCouplingUMesh(*this,recDeepCpy);
95 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
96 * The coordinates are shared between \a this and the returned instance.
98 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
99 * \sa MEDCouplingUMesh::deepCpy
101 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
103 checkConnectivityFullyDefined();
104 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
106 ret->setConnectivity(c,ci);
110 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
114 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
116 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
117 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
118 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
121 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
123 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
129 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
130 ret.push_back(_nodal_connec);
131 ret.push_back(_nodal_connec_index);
135 void MEDCouplingUMesh::updateTime() const
137 MEDCouplingPointSet::updateTime();
140 updateTimeWith(*_nodal_connec);
142 if(_nodal_connec_index)
144 updateTimeWith(*_nodal_connec_index);
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
153 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154 * then \a this mesh is most probably is writable, exchangeable and available for most
155 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156 * this method to check that all is in order with \a this mesh.
157 * \throw If the mesh dimension is not set.
158 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
159 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160 * \throw If the connectivity data array has more than one component.
161 * \throw If the connectivity data array has a named component.
162 * \throw If the connectivity index data array has more than one component.
163 * \throw If the connectivity index data array has a named component.
165 void MEDCouplingUMesh::checkCoherency() const
168 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
170 MEDCouplingPointSet::checkCoherency();
171 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
173 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
175 std::ostringstream message;
176 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177 throw INTERP_KERNEL::Exception(message.str().c_str());
182 if(_nodal_connec->getNumberOfComponents()!=1)
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184 if(_nodal_connec->getInfoOnComponent(0)!="")
185 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190 if(_nodal_connec_index)
192 if(_nodal_connec_index->getNumberOfComponents()!=1)
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194 if(_nodal_connec_index->getInfoOnComponent(0)!="")
195 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204 * then \a this mesh is most probably is writable, exchangeable and available for all
205 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206 * method thoroughly checks the nodal connectivity.
207 * \param [in] eps - a not used parameter.
208 * \throw If the mesh dimension is not set.
209 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
210 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211 * \throw If the connectivity data array has more than one component.
212 * \throw If the connectivity data array has a named component.
213 * \throw If the connectivity index data array has more than one component.
214 * \throw If the connectivity index data array has a named component.
215 * \throw If number of nodes defining an element does not correspond to the type of element.
216 * \throw If the nodal connectivity includes an invalid node id.
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
223 int meshDim=getMeshDimension();
224 int nbOfNodes=getNumberOfNodes();
225 int nbOfCells=getNumberOfCells();
226 const int *ptr=_nodal_connec->getConstPointer();
227 const int *ptrI=_nodal_connec_index->getConstPointer();
228 for(int i=0;i<nbOfCells;i++)
230 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231 if((int)cm.getDimension()!=meshDim)
233 std::ostringstream oss;
234 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235 throw INTERP_KERNEL::Exception(oss.str().c_str());
237 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
239 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
241 std::ostringstream oss;
242 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
243 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244 throw INTERP_KERNEL::Exception(oss.str().c_str());
246 if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
247 if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
249 std::ostringstream oss;
250 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " << nbOfNodesInCell;
251 oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
254 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
259 if(nodeId>=nbOfNodes)
261 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
262 throw INTERP_KERNEL::Exception(oss.str().c_str());
267 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
268 throw INTERP_KERNEL::Exception(oss.str().c_str());
272 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
274 std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
275 throw INTERP_KERNEL::Exception(oss.str().c_str());
284 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
285 * then \a this mesh is most probably is writable, exchangeable and available for all
286 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
287 * \param [in] eps - a not used parameter.
288 * \throw If the mesh dimension is not set.
289 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
290 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
291 * \throw If the connectivity data array has more than one component.
292 * \throw If the connectivity data array has a named component.
293 * \throw If the connectivity index data array has more than one component.
294 * \throw If the connectivity index data array has a named component.
295 * \throw If number of nodes defining an element does not correspond to the type of element.
296 * \throw If the nodal connectivity includes an invalid node id.
298 void MEDCouplingUMesh::checkCoherency2(double eps) const
300 checkCoherency1(eps);
304 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
305 * elements contained in the mesh. For more info on the mesh dimension see
306 * \ref MEDCouplingUMeshPage.
307 * \param [in] meshDim - a new mesh dimension.
308 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
310 void MEDCouplingUMesh::setMeshDimension(int meshDim)
312 if(meshDim<-1 || meshDim>3)
313 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
319 * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
320 * 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.
321 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
323 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
325 * \if ENABLE_EXAMPLES
326 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334 if(_nodal_connec_index)
336 _nodal_connec_index->decrRef();
340 _nodal_connec->decrRef();
342 _nodal_connec_index=DataArrayInt::New();
343 _nodal_connec_index->reserve(nbOfCells+1);
344 _nodal_connec_index->pushBackSilent(0);
345 _nodal_connec=DataArrayInt::New();
346 _nodal_connec->reserve(2*nbOfCells);
352 * Appends a cell to the connectivity array. For deeper understanding what is
353 * happening see \ref MEDCouplingUMeshNodalConnectivity.
354 * \param [in] type - type of cell to add.
355 * \param [in] size - number of nodes constituting this cell.
356 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
358 * \if ENABLE_EXAMPLES
359 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
365 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366 if(_nodal_connec_index==0)
367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368 if((int)cm.getDimension()==_mesh_dim)
371 if(size!=(int)cm.getNumberOfNodes())
373 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375 throw INTERP_KERNEL::Exception(oss.str().c_str());
377 int idx=_nodal_connec_index->back();
379 _nodal_connec_index->pushBackSilent(val);
380 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
385 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388 throw INTERP_KERNEL::Exception(oss.str().c_str());
393 * Compacts data arrays to release unused memory. This method is to be called after
394 * finishing cell insertion using \a this->insertNextCell().
396 * \if ENABLE_EXAMPLES
397 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
401 void MEDCouplingUMesh::finishInsertingCells()
403 _nodal_connec->pack();
404 _nodal_connec_index->pack();
405 _nodal_connec->declareAsNew();
406 _nodal_connec_index->declareAsNew();
411 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412 * Useful for python users.
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
416 return new MEDCouplingUMeshCellIterator(this);
420 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423 * Useful for python users.
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
427 if(!checkConsecutiveCellTypes())
428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429 return new MEDCouplingUMeshCellByTypeEntry(this);
433 * Returns a set of all cell types available in \a this mesh.
434 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435 * \warning this method does not throw any exception even if \a this is not defined.
436 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
444 * This method returns the sorted list of geometric types in \a this.
445 * 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
446 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
448 * \throw if connectivity in \a this is not correctly defined.
450 * \sa MEDCouplingMesh::getAllGeoTypes
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
454 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455 checkConnectivityFullyDefined();
456 int nbOfCells(getNumberOfCells());
459 if(getMeshLength()<1)
460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463 for(int i=1;i<nbOfCells;i++,ci++)
464 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
470 * This method is a method that compares \a this and \a other.
471 * This method compares \b all attributes, even names and component names.
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
476 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477 std::ostringstream oss; oss.precision(15);
478 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
481 reason="mesh given in input is not castable in MEDCouplingUMesh !";
484 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
486 if(_mesh_dim!=otherC->_mesh_dim)
488 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
492 if(_types!=otherC->_types)
494 oss << "umesh geometric type mismatch :\nThis geometric types are :";
495 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497 oss << "\nOther geometric types are :";
498 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
503 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504 if(_nodal_connec==0 || otherC->_nodal_connec==0)
506 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
509 if(_nodal_connec!=otherC->_nodal_connec)
510 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
512 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
515 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
518 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
521 if(_nodal_connec_index!=otherC->_nodal_connec_index)
522 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
524 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
531 * Checks if data arrays of this mesh (node coordinates, nodal
532 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
534 * \param [in] other - the mesh to compare with.
535 * \param [in] prec - precision value used to compare node coordinates.
536 * \return bool - \a true if the two meshes are same.
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
540 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
543 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
545 if(_mesh_dim!=otherC->_mesh_dim)
547 if(_types!=otherC->_types)
549 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550 if(_nodal_connec==0 || otherC->_nodal_connec==0)
552 if(_nodal_connec!=otherC->_nodal_connec)
553 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
555 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
558 if(_nodal_connec_index!=otherC->_nodal_connec_index)
559 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
565 * Checks if \a this and \a other meshes are geometrically equivalent with high
566 * probability, else an exception is thrown. The meshes are considered equivalent if
567 * (1) meshes contain the same number of nodes and the same number of elements of the
568 * same types (2) three cells of the two meshes (first, last and middle) are based
569 * on coincident nodes (with a specified precision).
570 * \param [in] other - the mesh to compare with.
571 * \param [in] prec - the precision used to compare nodes of the two meshes.
572 * \throw If the two meshes do not match.
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
576 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
583 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584 * cells each node belongs to.
585 * \warning For speed reasons, this method does not check if node ids in the nodal
586 * connectivity correspond to the size of node coordinates array.
587 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589 * dividing cell ids in \a revNodal into groups each referring to one
590 * node. Its every element (except the last one) is an index pointing to the
591 * first id of a group of cells. For example cells sharing the node #1 are
592 * described by following range of indices:
593 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595 * Number of cells sharing the *i*-th node is
596 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597 * \throw If the coordinates array is not set.
598 * \throw If the nodal connectivity of cells is not defined.
600 * \if ENABLE_EXAMPLES
601 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
608 int nbOfNodes=getNumberOfNodes();
609 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612 const int *conn=_nodal_connec->getConstPointer();
613 const int *connIndex=_nodal_connec_index->getConstPointer();
614 int nbOfCells=getNumberOfCells();
615 int nbOfEltsInRevNodal=0;
616 for(int eltId=0;eltId<nbOfCells;eltId++)
618 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621 if(*iter>=0)//for polyhedrons
623 nbOfEltsInRevNodal++;
624 revNodalIndxPtr[(*iter)+1]++;
627 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631 for(int eltId=0;eltId<nbOfCells;eltId++)
633 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636 if(*iter>=0)//for polyhedrons
637 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
654 if(cm.getOrientationStatus(nb,conn1,conn2))
661 class MinusOneSonsGenerator
664 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667 static const int DELTA=1;
669 const INTERP_KERNEL::CellModel& _cm;
672 class MinusOneSonsGeneratorBiQuadratic
675 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678 static const int DELTA=1;
680 const INTERP_KERNEL::CellModel& _cm;
683 class MinusTwoSonsGenerator
686 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689 static const int DELTA=2;
691 const INTERP_KERNEL::CellModel& _cm;
697 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699 * describing correspondence between cells of \a this and the result meshes are
700 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
701 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
703 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
704 * \warning For speed reasons, this method does not check if node ids in the nodal
705 * connectivity correspond to the size of node coordinates array.
706 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707 * to write this mesh to the MED file, its cells must be sorted using
708 * sortCellsInMEDFileFrmt().
709 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
710 * each cell of \a this mesh.
711 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712 * dividing cell ids in \a desc into groups each referring to one
713 * cell of \a this mesh. Its every element (except the last one) is an index
714 * pointing to the first id of a group of cells. For example cells of the
715 * result mesh bounding the cell #1 of \a this mesh are described by following
717 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722 * by each cell of the result mesh.
723 * \param [in,out] revDescIndx - the array, of length one more than number of cells
724 * in the result mesh,
725 * dividing cell ids in \a revDesc into groups each referring to one
726 * cell of the result mesh the same way as \a descIndx divides \a desc.
727 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728 * delete this mesh using decrRef() as it is no more needed.
729 * \throw If the coordinates array is not set.
730 * \throw If the nodal connectivity of cells is node defined.
731 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732 * revDescIndx == NULL.
734 * \if ENABLE_EXAMPLES
735 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
738 * \sa buildDescendingConnectivity2()
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
742 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
746 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750 * \sa MEDCouplingUMesh::buildDescendingConnectivity
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
755 if(getMeshDimension()!=3)
756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
761 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762 * this->getMeshDimension(), that bound cells of \a this mesh. In
763 * addition arrays describing correspondence between cells of \a this and the result
764 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
765 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766 * mesh. This method differs from buildDescendingConnectivity() in that apart
767 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768 * result meshes. So a positive id means that order of nodes in corresponding cells
769 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771 * i.e. cell ids are one-based.
772 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
773 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
774 * \warning For speed reasons, this method does not check if node ids in the nodal
775 * connectivity correspond to the size of node coordinates array.
776 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777 * to write this mesh to the MED file, its cells must be sorted using
778 * sortCellsInMEDFileFrmt().
779 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
780 * each cell of \a this mesh.
781 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782 * dividing cell ids in \a desc into groups each referring to one
783 * cell of \a this mesh. Its every element (except the last one) is an index
784 * pointing to the first id of a group of cells. For example cells of the
785 * result mesh bounding the cell #1 of \a this mesh are described by following
787 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792 * by each cell of the result mesh.
793 * \param [in,out] revDescIndx - the array, of length one more than number of cells
794 * in the result mesh,
795 * dividing cell ids in \a revDesc into groups each referring to one
796 * cell of the result mesh the same way as \a descIndx divides \a desc.
797 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798 * shares the node coordinates array with \a this mesh. The caller is to
799 * delete this mesh using decrRef() as it is no more needed.
800 * \throw If the coordinates array is not set.
801 * \throw If the nodal connectivity of cells is node defined.
802 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803 * revDescIndx == NULL.
805 * \if ENABLE_EXAMPLES
806 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
809 * \sa buildDescendingConnectivity()
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
813 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
817 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
819 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
820 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
822 * \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
823 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
824 * \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.
826 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
832 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
834 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
838 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
839 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
840 * excluding a set of meshdim-1 cells in input descending connectivity.
841 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
842 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
843 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
845 * \param [in] desc descending connectivity array.
846 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
847 * \param [in] revDesc reverse descending connectivity array.
848 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
849 * \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
850 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
851 * \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.
853 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
854 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
856 if(!desc || !descIndx || !revDesc || !revDescIndx)
857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
858 const int *descPtr=desc->getConstPointer();
859 const int *descIPtr=descIndx->getConstPointer();
860 const int *revDescPtr=revDesc->getConstPointer();
861 const int *revDescIPtr=revDescIndx->getConstPointer();
863 int nbCells=descIndx->getNumberOfTuples()-1;
864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
866 int *out1Ptr=out1->getPointer();
868 out0->reserve(desc->getNumberOfTuples());
869 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
871 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
873 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
875 out0->insertAtTheEnd(s.begin(),s.end());
877 *out1Ptr=out0->getNumberOfTuples();
879 neighbors=out0.retn();
880 neighborsIndx=out1.retn();
884 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
885 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
886 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
887 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
889 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
890 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
891 * \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.
893 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
896 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
898 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
903 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
908 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
913 mesh1D=const_cast<MEDCouplingUMesh *>(this);
919 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
922 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
923 mesh1D->getReverseNodalConnectivity(desc,descIndx);
924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
925 ret0->alloc(desc->getNumberOfTuples(),1);
926 int *r0Pt(ret0->getPointer());
927 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
928 for(int i=0;i<nbNodes;i++,rni++)
930 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
931 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
933 neighbors=ret0.retn();
934 neighborsIdx=descIndx.retn();
940 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
941 * For speed reasons no check of this will be done.
943 template<class SonsGenerator>
944 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
946 if(!desc || !descIndx || !revDesc || !revDescIndx)
947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
948 checkConnectivityFullyDefined();
949 int nbOfCells=getNumberOfCells();
950 int nbOfNodes=getNumberOfNodes();
951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
952 int *revNodalIndxPtr=revNodalIndx->getPointer();
953 const int *conn=_nodal_connec->getConstPointer();
954 const int *connIndex=_nodal_connec_index->getConstPointer();
955 std::string name="Mesh constituent of "; name+=getName();
956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
957 ret->setCoords(getCoords());
958 ret->allocateCells(2*nbOfCells);
959 descIndx->alloc(nbOfCells+1,1);
960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
961 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
962 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
964 int pos=connIndex[eltId];
965 int posP1=connIndex[eltId+1];
966 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
967 SonsGenerator sg(cm);
968 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
969 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
970 for(unsigned i=0;i<nbOfSons;i++)
972 INTERP_KERNEL::NormalizedCellType cmsId;
973 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
974 for(unsigned k=0;k<nbOfNodesSon;k++)
976 revNodalIndxPtr[tmp[k]+1]++;
977 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
978 revDesc2->pushBackSilent(eltId);
980 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
982 int nbOfCellsM1=ret->getNumberOfCells();
983 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
985 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
986 int *revNodalPtr=revNodal->getPointer();
987 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
988 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
989 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
991 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
992 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
993 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
994 if(*iter>=0)//for polyhedrons
995 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
998 DataArrayInt *commonCells=0,*commonCellsI=0;
999 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1001 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1002 int newNbOfCellsM1=-1;
1003 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1004 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1005 std::vector<bool> isImpacted(nbOfCellsM1,false);
1006 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1007 for(int work2=work[0];work2!=work[1];work2++)
1008 isImpacted[commonCellsPtr[work2]]=true;
1009 const int *o2nM1Ptr=o2nM1->getConstPointer();
1010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1011 const int *n2oM1Ptr=n2oM1->getConstPointer();
1012 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1013 ret2->copyTinyInfoFrom(this);
1014 desc->alloc(descIndx->back(),1);
1015 int *descPtr=desc->getPointer();
1016 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1017 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1020 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1023 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1025 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1026 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1029 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1032 revDesc->reserve(newNbOfCellsM1);
1033 revDescIndx->alloc(newNbOfCellsM1+1,1);
1034 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1035 const int *revDesc2Ptr=revDesc2->getConstPointer();
1036 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1038 int oldCellIdM1=n2oM1Ptr[i];
1039 if(!isImpacted[oldCellIdM1])
1041 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1042 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1046 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1047 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1048 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1056 struct MEDCouplingAccVisit
1058 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1059 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1060 int _new_nb_of_nodes;
1066 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1067 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1068 * array of cell ids. Pay attention that after conversion all algorithms work slower
1069 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1070 * conversion due presence of invalid ids in the array of cells to convert, as a
1071 * result \a this mesh contains some already converted elements. In this case the 2D
1072 * mesh remains valid but 3D mesh becomes \b inconsistent!
1073 * \warning This method can significantly modify the order of geometric types in \a this,
1074 * hence, to write this mesh to the MED file, its cells must be sorted using
1075 * sortCellsInMEDFileFrmt().
1076 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1077 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1078 * cellIdsToConvertBg.
1079 * \throw If the coordinates array is not set.
1080 * \throw If the nodal connectivity of cells is node defined.
1081 * \throw If dimension of \a this mesh is not either 2 or 3.
1083 * \if ENABLE_EXAMPLES
1084 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1085 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1088 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1090 checkFullyDefined();
1091 int dim=getMeshDimension();
1093 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1094 int nbOfCells(getNumberOfCells());
1097 const int *connIndex=_nodal_connec_index->getConstPointer();
1098 int *conn=_nodal_connec->getPointer();
1099 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1101 if(*iter>=0 && *iter<nbOfCells)
1103 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1104 if(!cm.isQuadratic())
1105 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1107 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1111 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1112 oss << " in range [0," << nbOfCells << ") !";
1113 throw INTERP_KERNEL::Exception(oss.str().c_str());
1119 int *connIndex(_nodal_connec_index->getPointer());
1120 const int *connOld(_nodal_connec->getConstPointer());
1121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1122 std::vector<bool> toBeDone(nbOfCells,false);
1123 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1125 if(*iter>=0 && *iter<nbOfCells)
1126 toBeDone[*iter]=true;
1129 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130 oss << " in range [0," << nbOfCells << ") !";
1131 throw INTERP_KERNEL::Exception(oss.str().c_str());
1134 for(int cellId=0;cellId<nbOfCells;cellId++)
1136 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1137 int lgthOld(posP1-pos-1);
1138 if(toBeDone[cellId])
1140 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1141 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1142 int *tmp(new int[nbOfFaces*lgthOld+1]);
1143 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1144 for(unsigned j=0;j<nbOfFaces;j++)
1146 INTERP_KERNEL::NormalizedCellType type;
1147 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1151 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1152 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1153 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1158 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1159 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1162 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1168 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1169 * polyhedrons (if \a this is a 3D mesh).
1170 * \warning As this method is purely for user-friendliness and no optimization is
1171 * done to avoid construction of a useless vector, this method can be costly
1173 * \throw If the coordinates array is not set.
1174 * \throw If the nodal connectivity of cells is node defined.
1175 * \throw If dimension of \a this mesh is not either 2 or 3.
1177 void MEDCouplingUMesh::convertAllToPoly()
1179 int nbOfCells=getNumberOfCells();
1180 std::vector<int> cellIds(nbOfCells);
1181 for(int i=0;i<nbOfCells;i++)
1183 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1187 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1188 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1189 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1190 * base facet of the volume and the second half of nodes describes an opposite facet
1191 * having the same number of nodes as the base one. This method converts such
1192 * connectivity to a valid polyhedral format where connectivity of each facet is
1193 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1194 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1195 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1196 * a correct orientation of the first facet of a polyhedron, else orientation of a
1197 * corrected cell is reverse.<br>
1198 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1199 * it releases the user from boring description of polyhedra connectivity in the valid
1201 * \throw If \a this->getMeshDimension() != 3.
1202 * \throw If \a this->getSpaceDimension() != 3.
1203 * \throw If the nodal connectivity of cells is not defined.
1204 * \throw If the coordinates array is not set.
1205 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1206 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1208 * \if ENABLE_EXAMPLES
1209 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1210 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1213 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1215 checkFullyDefined();
1216 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1218 int nbOfCells=getNumberOfCells();
1219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1220 newCi->alloc(nbOfCells+1,1);
1221 int *newci=newCi->getPointer();
1222 const int *ci=_nodal_connec_index->getConstPointer();
1223 const int *c=_nodal_connec->getConstPointer();
1225 for(int i=0;i<nbOfCells;i++)
1227 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1228 if(type==INTERP_KERNEL::NORM_POLYHED)
1230 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1232 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1233 throw INTERP_KERNEL::Exception(oss.str().c_str());
1235 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1238 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 !";
1239 throw INTERP_KERNEL::Exception(oss.str().c_str());
1242 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)
1245 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1248 newC->alloc(newci[nbOfCells],1);
1249 int *newc=newC->getPointer();
1250 for(int i=0;i<nbOfCells;i++)
1252 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1253 if(type==INTERP_KERNEL::NORM_POLYHED)
1255 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1256 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1258 for(std::size_t j=0;j<n1;j++)
1260 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1262 newc[n1+5*j+1]=c[ci[i]+1+j];
1263 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1264 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1265 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1270 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1272 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1273 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1278 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1279 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1280 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1281 * to write this mesh to the MED file, its cells must be sorted using
1282 * sortCellsInMEDFileFrmt().
1283 * \return \c true if at least one cell has been converted, \c false else. In the
1284 * last case the nodal connectivity remains unchanged.
1285 * \throw If the coordinates array is not set.
1286 * \throw If the nodal connectivity of cells is not defined.
1287 * \throw If \a this->getMeshDimension() < 0.
1289 bool MEDCouplingUMesh::unPolyze()
1291 checkFullyDefined();
1292 int mdim=getMeshDimension();
1294 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1297 int nbOfCells=getNumberOfCells();
1300 int initMeshLgth=getMeshLength();
1301 int *conn=_nodal_connec->getPointer();
1302 int *index=_nodal_connec_index->getPointer();
1307 for(int i=0;i<nbOfCells;i++)
1309 lgthOfCurCell=index[i+1]-posOfCurCell;
1310 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1311 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1312 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1316 switch(cm.getDimension())
1320 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1321 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1322 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1327 int nbOfFaces,lgthOfPolyhConn;
1328 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1329 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1334 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1338 ret=ret || (newType!=type);
1339 conn[newPos]=newType;
1341 posOfCurCell=index[i+1];
1346 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1347 newPos+=lgthOfCurCell;
1348 posOfCurCell+=lgthOfCurCell;
1352 if(newPos!=initMeshLgth)
1353 _nodal_connec->reAlloc(newPos);
1360 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1361 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1362 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1364 * \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
1367 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1369 checkFullyDefined();
1370 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1372 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1373 coords->recenterForMaxPrecision(eps);
1375 int nbOfCells=getNumberOfCells();
1376 const int *conn=_nodal_connec->getConstPointer();
1377 const int *index=_nodal_connec_index->getConstPointer();
1378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1379 connINew->alloc(nbOfCells+1,1);
1380 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1383 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1385 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1387 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1391 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1392 *connINewPtr=connNew->getNumberOfTuples();
1395 setConnectivity(connNew,connINew,false);
1399 * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1400 * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1401 * the format of the returned DataArrayInt instance.
1403 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1404 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1406 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1408 checkConnectivityFullyDefined();
1409 int nbOfCells=getNumberOfCells();
1410 const int *connIndex=_nodal_connec_index->getConstPointer();
1411 const int *conn=_nodal_connec->getConstPointer();
1412 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1413 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1414 std::vector<bool> retS(maxElt,false);
1415 for(int i=0;i<nbOfCells;i++)
1416 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1420 for(int i=0;i<maxElt;i++)
1423 DataArrayInt *ret=DataArrayInt::New();
1425 int *retPtr=ret->getPointer();
1426 for(int i=0;i<maxElt;i++)
1433 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1434 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1436 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1438 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1439 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1440 for(int i=0;i<nbOfCells;i++)
1441 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1444 if(conn[j]<nbOfNodes)
1445 nodeIdsInUse[conn[j]]=true;
1448 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1449 throw INTERP_KERNEL::Exception(oss.str().c_str());
1455 * Finds nodes not used in any cell and returns an array giving a new id to every node
1456 * by excluding the unused nodes, for which the array holds -1. The result array is
1457 * a mapping in "Old to New" mode.
1458 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1459 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1460 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1461 * if the node is unused or a new id else. The caller is to delete this
1462 * array using decrRef() as it is no more needed.
1463 * \throw If the coordinates array is not set.
1464 * \throw If the nodal connectivity of cells is not defined.
1465 * \throw If the nodal connectivity includes an invalid id.
1467 * \if ENABLE_EXAMPLES
1468 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1469 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1471 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1473 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1476 int nbOfNodes(getNumberOfNodes());
1477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1478 ret->alloc(nbOfNodes,1);
1479 int *traducer=ret->getPointer();
1480 std::fill(traducer,traducer+nbOfNodes,-1);
1481 int nbOfCells=getNumberOfCells();
1482 const int *connIndex=_nodal_connec_index->getConstPointer();
1483 const int *conn=_nodal_connec->getConstPointer();
1484 for(int i=0;i<nbOfCells;i++)
1485 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1488 if(conn[j]<nbOfNodes)
1489 traducer[conn[j]]=1;
1492 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1493 throw INTERP_KERNEL::Exception(oss.str().c_str());
1496 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1497 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1502 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1503 * For each cell in \b this the number of nodes constituting cell is computed.
1504 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1505 * So for pohyhedrons some nodes can be counted several times in the returned result.
1507 * \return a newly allocated array
1508 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1510 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1512 checkConnectivityFullyDefined();
1513 int nbOfCells=getNumberOfCells();
1514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1515 ret->alloc(nbOfCells,1);
1516 int *retPtr=ret->getPointer();
1517 const int *conn=getNodalConnectivity()->getConstPointer();
1518 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1519 for(int i=0;i<nbOfCells;i++,retPtr++)
1521 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1522 *retPtr=connI[i+1]-connI[i]-1;
1524 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1530 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1531 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1533 * \return DataArrayInt * - new object to be deallocated by the caller.
1534 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1536 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1538 checkConnectivityFullyDefined();
1539 int nbOfCells=getNumberOfCells();
1540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1541 ret->alloc(nbOfCells,1);
1542 int *retPtr=ret->getPointer();
1543 const int *conn=getNodalConnectivity()->getConstPointer();
1544 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1545 for(int i=0;i<nbOfCells;i++,retPtr++)
1547 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1548 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1549 *retPtr=(int)s.size();
1553 *retPtr=(int)s.size();
1560 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1561 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1563 * \return a newly allocated array
1565 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1567 checkConnectivityFullyDefined();
1568 int nbOfCells=getNumberOfCells();
1569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1570 ret->alloc(nbOfCells,1);
1571 int *retPtr=ret->getPointer();
1572 const int *conn=getNodalConnectivity()->getConstPointer();
1573 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1574 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1576 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1577 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1583 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1584 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1585 * array mean that the corresponding old node is no more used.
1586 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1587 * this->getNumberOfNodes() before call of this method. The caller is to
1588 * delete this array using decrRef() as it is no more needed.
1589 * \throw If the coordinates array is not set.
1590 * \throw If the nodal connectivity of cells is not defined.
1591 * \throw If the nodal connectivity includes an invalid id.
1592 * \sa areAllNodesFetched
1594 * \if ENABLE_EXAMPLES
1595 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1596 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1599 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1601 return MEDCouplingPointSet::zipCoordsTraducer();
1605 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1606 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1608 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1613 return AreCellsEqual0(conn,connI,cell1,cell2);
1615 return AreCellsEqual1(conn,connI,cell1,cell2);
1617 return AreCellsEqual2(conn,connI,cell1,cell2);
1619 return AreCellsEqual3(conn,connI,cell1,cell2);
1621 return AreCellsEqual7(conn,connI,cell1,cell2);
1623 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1627 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1629 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1631 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1637 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1639 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1641 int sz=connI[cell1+1]-connI[cell1];
1642 if(sz==connI[cell2+1]-connI[cell2])
1644 if(conn[connI[cell1]]==conn[connI[cell2]])
1646 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1647 unsigned dim=cm.getDimension();
1653 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1654 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1655 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1656 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1657 return work!=tmp+sz1?1:0;
1660 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1663 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1670 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1672 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1674 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1676 if(conn[connI[cell1]]==conn[connI[cell2]])
1678 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1679 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1687 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1689 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1691 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1693 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1701 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1703 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1705 int sz=connI[cell1+1]-connI[cell1];
1706 if(sz==connI[cell2+1]-connI[cell2])
1708 if(conn[connI[cell1]]==conn[connI[cell2]])
1710 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1711 unsigned dim=cm.getDimension();
1717 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1718 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1719 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1720 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1725 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1726 std::reverse_iterator<int *> it2((int *)tmp);
1727 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1733 return work!=tmp+sz1?1:0;
1736 {//case of SEG2 and SEG3
1737 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1739 if(!cm.isQuadratic())
1741 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1742 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1743 if(std::equal(it1,it2,conn+connI[cell2]+1))
1749 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])
1756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1763 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1764 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1765 * and result remains unchanged.
1766 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1767 * If in 'candidates' pool -1 value is considered as an empty value.
1768 * WARNING this method returns only ONE set of result !
1770 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1772 if(candidates.size()<1)
1775 std::vector<int>::const_iterator iter=candidates.begin();
1776 int start=(*iter++);
1777 for(;iter!=candidates.end();iter++)
1779 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1784 result->pushBackSilent(start);
1788 result->pushBackSilent(*iter);
1790 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1797 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1798 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1800 * \param [in] compType input specifying the technique used to compare cells each other.
1801 * - 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.
1802 * - 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)
1803 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1804 * - 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
1805 * can be used for users not sensitive to orientation of cell
1806 * \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.
1807 * \param [out] commonCells
1808 * \param [out] commonCellsI
1809 * \return the correspondance array old to new in a newly allocated array.
1812 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1815 getReverseNodalConnectivity(revNodal,revNodalI);
1816 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1819 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1820 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1823 int nbOfCells=nodalI->getNumberOfTuples()-1;
1824 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1825 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1826 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1827 std::vector<bool> isFetched(nbOfCells,false);
1830 for(int i=0;i<nbOfCells;i++)
1834 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1835 std::vector<int> v,v2;
1836 if(connOfNode!=connPtr+connIPtr[i+1])
1838 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1839 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1842 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1846 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1847 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1848 v2.resize(std::distance(v2.begin(),it));
1852 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1854 int pos=commonCellsI->back();
1855 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1856 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1857 isFetched[*it]=true;
1865 for(int i=startCellId;i<nbOfCells;i++)
1869 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1870 std::vector<int> v,v2;
1871 if(connOfNode!=connPtr+connIPtr[i+1])
1873 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1876 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1880 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1881 v2.resize(std::distance(v2.begin(),it));
1885 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1887 int pos=commonCellsI->back();
1888 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1889 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1890 isFetched[*it]=true;
1896 commonCellsArr=commonCells.retn();
1897 commonCellsIArr=commonCellsI.retn();
1901 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1902 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1903 * than \a other->getNumberOfCells() in the returned array means that there is no
1904 * corresponding cell in \a this mesh.
1905 * It is expected that \a this and \a other meshes share the same node coordinates
1906 * array, if it is not so an exception is thrown.
1907 * \param [in] other - the mesh to compare with.
1908 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1909 * valid values [0,1,2], see zipConnectivityTraducer().
1910 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1911 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1912 * values. The caller is to delete this array using
1913 * decrRef() as it is no more needed.
1914 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1917 * \if ENABLE_EXAMPLES
1918 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1919 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1921 * \sa checkDeepEquivalOnSameNodesWith()
1922 * \sa checkGeoEquivalWith()
1924 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1926 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1927 int nbOfCells=getNumberOfCells();
1928 static const int possibleCompType[]={0,1,2};
1929 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1931 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1932 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1934 throw INTERP_KERNEL::Exception(oss.str().c_str());
1936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1937 arr=o2n->substr(nbOfCells);
1938 arr->setName(other->getName());
1940 if(other->getNumberOfCells()==0)
1942 return arr->getMaxValue(tmp)<nbOfCells;
1946 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1947 * This method tries to determine if \b other is fully included in \b this.
1948 * The main difference is that this method is not expected to throw exception.
1949 * This method has two outputs :
1951 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1952 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1954 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1957 DataArrayInt *commonCells=0,*commonCellsI=0;
1958 int thisNbCells=getNumberOfCells();
1959 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1961 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1962 int otherNbCells=other->getNumberOfCells();
1963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1964 arr2->alloc(otherNbCells,1);
1965 arr2->fillWithZero();
1966 int *arr2Ptr=arr2->getPointer();
1967 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1968 for(int i=0;i<nbOfCommon;i++)
1970 int start=commonCellsPtr[commonCellsIPtr[i]];
1971 if(start<thisNbCells)
1973 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1975 int sig=commonCellsPtr[j]>0?1:-1;
1976 int val=std::abs(commonCellsPtr[j])-1;
1977 if(val>=thisNbCells)
1978 arr2Ptr[val-thisNbCells]=sig*(start+1);
1982 arr2->setName(other->getName());
1983 if(arr2->presenceOfValue(0))
1989 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1992 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1993 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1995 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1996 std::vector<const MEDCouplingUMesh *> ms(2);
1999 return MergeUMeshesOnSameCoords(ms);
2003 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2004 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2005 * cellIds is not given explicitely but by a range python like.
2007 * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2008 * \return a newly allocated
2010 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2011 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2013 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2015 if(getMeshDimension()!=-1)
2016 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2019 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2021 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2023 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2025 return const_cast<MEDCouplingUMesh *>(this);
2030 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2031 * The result mesh shares or not the node coordinates array with \a this mesh depending
2032 * on \a keepCoords parameter.
2033 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2034 * to write this mesh to the MED file, its cells must be sorted using
2035 * sortCellsInMEDFileFrmt().
2036 * \param [in] begin - an array of cell ids to include to the new mesh.
2037 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2038 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2039 * array of \a this mesh, else "free" nodes are removed from the result mesh
2040 * by calling zipCoords().
2041 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2042 * to delete this mesh using decrRef() as it is no more needed.
2043 * \throw If the coordinates array is not set.
2044 * \throw If the nodal connectivity of cells is not defined.
2045 * \throw If any cell id in the array \a begin is not valid.
2047 * \if ENABLE_EXAMPLES
2048 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2049 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2052 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2054 if(getMeshDimension()!=-1)
2055 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2059 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2061 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2063 return const_cast<MEDCouplingUMesh *>(this);
2068 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2070 * 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.
2071 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2072 * The number of cells of \b this will remain the same with this method.
2074 * \param [in] begin begin of cell ids (included) of cells in this to assign
2075 * \param [in] end end of cell ids (excluded) of cells in this to assign
2076 * \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 ).
2077 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2079 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2081 checkConnectivityFullyDefined();
2082 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2083 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2084 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2085 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2087 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2088 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2089 throw INTERP_KERNEL::Exception(oss.str().c_str());
2091 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2092 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2094 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2095 throw INTERP_KERNEL::Exception(oss.str().c_str());
2097 int nbOfCells=getNumberOfCells();
2098 bool easyAssign=true;
2099 const int *connI=_nodal_connec_index->getConstPointer();
2100 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2101 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2103 if(*it>=0 && *it<nbOfCells)
2105 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2109 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2110 throw INTERP_KERNEL::Exception(oss.str().c_str());
2115 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2120 DataArrayInt *arrOut=0,*arrIOut=0;
2121 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2124 setConnectivity(arrOut,arrIOut,true);
2128 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2130 checkConnectivityFullyDefined();
2131 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2132 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2133 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2134 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2136 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2137 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2138 throw INTERP_KERNEL::Exception(oss.str().c_str());
2140 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2141 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2143 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2144 throw INTERP_KERNEL::Exception(oss.str().c_str());
2146 int nbOfCells=getNumberOfCells();
2147 bool easyAssign=true;
2148 const int *connI=_nodal_connec_index->getConstPointer();
2149 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2151 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2153 if(it>=0 && it<nbOfCells)
2155 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2159 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2160 throw INTERP_KERNEL::Exception(oss.str().c_str());
2165 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2170 DataArrayInt *arrOut=0,*arrIOut=0;
2171 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2174 setConnectivity(arrOut,arrIOut,true);
2179 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2180 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2181 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2182 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2184 * \param [in] begin input start of array of node ids.
2185 * \param [in] end input end of array of node ids.
2186 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2187 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2189 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2191 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2192 checkConnectivityFullyDefined();
2194 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2195 std::vector<bool> fastFinder(sz,false);
2196 for(const int *work=begin;work!=end;work++)
2197 if(*work>=0 && *work<sz)
2198 fastFinder[*work]=true;
2199 int nbOfCells=getNumberOfCells();
2200 const int *conn=getNodalConnectivity()->getConstPointer();
2201 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2202 for(int i=0;i<nbOfCells;i++)
2204 int ref=0,nbOfHit=0;
2205 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2209 if(fastFinder[*work2])
2212 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2213 cellIdsKept->pushBackSilent(i);
2215 cellIdsKeptArr=cellIdsKept.retn();
2219 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2220 * this->getMeshDimension(), that bound some cells of \a this mesh.
2221 * The cells of lower dimension to include to the result mesh are selected basing on
2222 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2223 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2224 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2225 * created mesh shares the node coordinates array with \a this mesh.
2226 * \param [in] begin - the array of node ids.
2227 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2228 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2229 * array \a begin are added, else cells whose any node is in the
2230 * array \a begin are added.
2231 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2232 * to delete this mesh using decrRef() as it is no more needed.
2233 * \throw If the coordinates array is not set.
2234 * \throw If the nodal connectivity of cells is not defined.
2235 * \throw If any node id in \a begin is not valid.
2237 * \if ENABLE_EXAMPLES
2238 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2239 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2242 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2245 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2246 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2247 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2248 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2252 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2253 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2254 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2255 * array of \a this mesh, else "free" nodes are removed from the result mesh
2256 * by calling zipCoords().
2257 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2258 * to delete this mesh using decrRef() as it is no more needed.
2259 * \throw If the coordinates array is not set.
2260 * \throw If the nodal connectivity of cells is not defined.
2262 * \if ENABLE_EXAMPLES
2263 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2264 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2267 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2269 DataArrayInt *desc=DataArrayInt::New();
2270 DataArrayInt *descIndx=DataArrayInt::New();
2271 DataArrayInt *revDesc=DataArrayInt::New();
2272 DataArrayInt *revDescIndx=DataArrayInt::New();
2274 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2277 descIndx->decrRef();
2278 int nbOfCells=meshDM1->getNumberOfCells();
2279 const int *revDescIndxC=revDescIndx->getConstPointer();
2280 std::vector<int> boundaryCells;
2281 for(int i=0;i<nbOfCells;i++)
2282 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2283 boundaryCells.push_back(i);
2284 revDescIndx->decrRef();
2285 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2290 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2291 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2292 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2294 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2296 checkFullyDefined();
2297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2302 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2303 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2307 const int *revDescPtr=revDesc->getConstPointer();
2308 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2309 int nbOfCells=getNumberOfCells();
2310 std::vector<bool> ret1(nbOfCells,false);
2312 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2313 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2314 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2316 DataArrayInt *ret2=DataArrayInt::New();
2318 int *ret2Ptr=ret2->getPointer();
2320 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2323 ret2->setName("BoundaryCells");
2328 * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2329 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2330 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2331 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2333 * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2334 * 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
2335 * equals a cell in \b otherDimM1OnSameCoords.
2337 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2338 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2340 * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2341 * \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
2342 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2344 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2346 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2347 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2348 checkConnectivityFullyDefined();
2349 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2350 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2351 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2354 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2357 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2358 DataArrayInt *idsOtherInConsti=0;
2359 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2364 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2365 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2367 s1arr_renum1->sort();
2368 cellIdsRk0=s0arr.retn();
2369 //cellIdsRk1=s_renum1.retn();
2370 cellIdsRk1=s1arr_renum1.retn();
2374 * 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
2375 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2377 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2379 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2382 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2386 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2387 revDesc=0; desc=0; descIndx=0;
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2390 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2394 * Finds nodes lying on the boundary of \a this mesh.
2395 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2396 * nodes. The caller is to delete this array using decrRef() as it is no
2398 * \throw If the coordinates array is not set.
2399 * \throw If the nodal connectivity of cells is node defined.
2401 * \if ENABLE_EXAMPLES
2402 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2403 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2406 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2408 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2409 return skin->computeFetchedNodeIds();
2412 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2415 return const_cast<MEDCouplingUMesh *>(this);
2419 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2420 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2421 * 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.
2422 * 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.
2423 * 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.
2425 * \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
2426 * parameter is altered during the call.
2427 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2428 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2429 * \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.
2431 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2433 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2434 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2436 typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2438 checkFullyDefined();
2439 otherDimM1OnSameCoords.checkFullyDefined();
2440 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2441 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2442 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2444 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2445 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2446 DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2447 DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2448 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2449 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2450 DAInt s1=m0Part->computeFetchedNodeIds();
2451 DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2452 DAInt s3=s2->buildSubstraction(s1);
2453 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2455 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2456 int nCells2 = m0Part2->getNumberOfCells();
2457 DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2458 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2459 // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2460 DataArrayInt *tmp00=0,*tmp11=0;
2461 MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2462 DAInt neighInit00(tmp00);
2463 DAInt neighIInit00(tmp11);
2464 // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2465 DataArrayInt *idsTmp=0;
2466 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2469 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2470 // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2471 // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2472 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2473 DataArrayInt *tmp0=0,*tmp1=0;
2474 // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2475 // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2476 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2477 DAInt neigh00(tmp0);
2478 DAInt neighI00(tmp1);
2480 // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2481 int seed = 0, nIter = 0;
2482 int nIterMax = nCells2+1; // Safety net for the loop
2483 DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2484 hitCells->fillWithValue(-1);
2485 DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2486 cellsToModifyConn0_torenum->alloc(0,1);
2487 while (nIter < nIterMax)
2489 DAInt t = hitCells->getIdsEqual(-1);
2490 if (!t->getNumberOfTuples())
2492 // Connex zone without the crack (to compute the next seed really)
2494 DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2496 for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2497 hitCells->setIJ(*ptr,0,1);
2498 // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2499 DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2500 cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2501 // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2502 DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2503 DAInt nonHitCells = hitCells->getIdsEqual(-1);
2504 DAInt intersec = nonHitCells->buildIntersection(comple);
2505 if (intersec->getNumberOfTuples())
2506 { seed = intersec->getIJ(0,0); }
2511 if (nIter >= nIterMax)
2512 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2514 DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2515 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2516 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2518 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2519 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2520 nodeIdsToDuplicate=s3.retn();
2524 * This method operates a modification of the connectivity and coords in \b this.
2525 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2526 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2527 * 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
2528 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2529 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2531 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2533 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2534 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2536 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2538 int nbOfNodes=getNumberOfNodes();
2539 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2540 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2544 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2545 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2547 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2549 * \sa renumberNodesInConn
2551 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2553 checkConnectivityFullyDefined();
2554 int *conn(getNodalConnectivity()->getPointer());
2555 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2556 int nbOfCells(getNumberOfCells());
2557 for(int i=0;i<nbOfCells;i++)
2558 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2560 int& node=conn[iconn];
2561 if(node>=0)//avoid polyhedron separator
2566 _nodal_connec->declareAsNew();
2571 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2572 * 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
2575 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2577 checkConnectivityFullyDefined();
2578 int *conn(getNodalConnectivity()->getPointer());
2579 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2580 int nbOfCells(getNumberOfCells());
2581 for(int i=0;i<nbOfCells;i++)
2582 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2584 int& node=conn[iconn];
2585 if(node>=0)//avoid polyhedron separator
2587 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2588 if(it!=newNodeNumbersO2N.end())
2594 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2595 throw INTERP_KERNEL::Exception(oss.str().c_str());
2599 _nodal_connec->declareAsNew();
2604 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2605 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2606 * This method is a generalization of shiftNodeNumbersInConn().
2607 * \warning This method performs no check of validity of new ids. **Use it with care !**
2608 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2609 * this->getNumberOfNodes(), in "Old to New" mode.
2610 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2611 * \throw If the nodal connectivity of cells is not defined.
2613 * \if ENABLE_EXAMPLES
2614 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2615 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2618 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2620 checkConnectivityFullyDefined();
2621 int *conn=getNodalConnectivity()->getPointer();
2622 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2623 int nbOfCells(getNumberOfCells());
2624 for(int i=0;i<nbOfCells;i++)
2625 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2627 int& node=conn[iconn];
2628 if(node>=0)//avoid polyhedron separator
2630 node=newNodeNumbersO2N[node];
2633 _nodal_connec->declareAsNew();
2638 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2639 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2640 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2642 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2644 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2646 checkConnectivityFullyDefined();
2647 int *conn=getNodalConnectivity()->getPointer();
2648 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2649 int nbOfCells=getNumberOfCells();
2650 for(int i=0;i<nbOfCells;i++)
2651 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2653 int& node=conn[iconn];
2654 if(node>=0)//avoid polyhedron separator
2659 _nodal_connec->declareAsNew();
2664 * This method operates a modification of the connectivity in \b this.
2665 * 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.
2666 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2667 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2668 * 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
2669 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2670 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2672 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2673 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2675 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2676 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2677 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2679 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2681 checkConnectivityFullyDefined();
2682 std::map<int,int> m;
2684 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2686 int *conn=getNodalConnectivity()->getPointer();
2687 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2688 int nbOfCells=getNumberOfCells();
2689 for(int i=0;i<nbOfCells;i++)
2690 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2692 int& node=conn[iconn];
2693 if(node>=0)//avoid polyhedron separator
2695 std::map<int,int>::iterator it=m.find(node);
2704 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2706 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2707 * After the call of this method the number of cells remains the same as before.
2709 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2710 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2711 * be strictly in [0;this->getNumberOfCells()).
2713 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2714 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2715 * should be contained in[0;this->getNumberOfCells()).
2717 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2719 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2721 checkConnectivityFullyDefined();
2722 int nbCells=getNumberOfCells();
2723 const int *array=old2NewBg;
2725 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2727 const int *conn=_nodal_connec->getConstPointer();
2728 const int *connI=_nodal_connec_index->getConstPointer();
2729 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2731 const int *n2oPtr=n2o->begin();
2732 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2733 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2734 newConn->copyStringInfoFrom(*_nodal_connec);
2735 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2736 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2737 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2739 int *newC=newConn->getPointer();
2740 int *newCI=newConnI->getPointer();
2743 for(int i=0;i<nbCells;i++)
2746 int nbOfElts=connI[pos+1]-connI[pos];
2747 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2752 setConnectivity(newConn,newConnI);
2754 free(const_cast<int *>(array));
2758 * Finds cells whose bounding boxes intersect a given bounding box.
2759 * \param [in] bbox - an array defining the bounding box via coordinates of its
2760 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2762 * \param [in] eps - a factor used to increase size of the bounding box of cell
2763 * before comparing it with \a bbox. This factor is multiplied by the maximal
2764 * extent of the bounding box of cell to produce an addition to this bounding box.
2765 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2766 * cells. The caller is to delete this array using decrRef() as it is no more
2768 * \throw If the coordinates array is not set.
2769 * \throw If the nodal connectivity of cells is not defined.
2771 * \if ENABLE_EXAMPLES
2772 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2773 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2776 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2778 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2779 if(getMeshDimension()==-1)
2781 elems->pushBackSilent(0);
2782 return elems.retn();
2784 int dim=getSpaceDimension();
2785 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2786 const int* conn = getNodalConnectivity()->getConstPointer();
2787 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2788 const double* coords = getCoords()->getConstPointer();
2789 int nbOfCells=getNumberOfCells();
2790 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2792 for (int i=0; i<dim; i++)
2794 elem_bb[i*2]=std::numeric_limits<double>::max();
2795 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2798 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2800 int node= conn[inode];
2801 if(node>=0)//avoid polyhedron separator
2803 for (int idim=0; idim<dim; idim++)
2805 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2807 elem_bb[idim*2] = coords[node*dim+idim] ;
2809 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2811 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2816 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2817 elems->pushBackSilent(ielem);
2819 return elems.retn();
2823 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2824 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2825 * added in 'elems' parameter.
2827 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2830 if(getMeshDimension()==-1)
2832 elems->pushBackSilent(0);
2833 return elems.retn();
2835 int dim=getSpaceDimension();
2836 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2837 const int* conn = getNodalConnectivity()->getConstPointer();
2838 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2839 const double* coords = getCoords()->getConstPointer();
2840 int nbOfCells=getNumberOfCells();
2841 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2843 for (int i=0; i<dim; i++)
2845 elem_bb[i*2]=std::numeric_limits<double>::max();
2846 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2849 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2851 int node= conn[inode];
2852 if(node>=0)//avoid polyhedron separator
2854 for (int idim=0; idim<dim; idim++)
2856 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2858 elem_bb[idim*2] = coords[node*dim+idim] ;
2860 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2862 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2867 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2868 elems->pushBackSilent(ielem);
2870 return elems.retn();
2874 * Returns a type of a cell by its id.
2875 * \param [in] cellId - the id of the cell of interest.
2876 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2877 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2879 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2881 const int *ptI=_nodal_connec_index->getConstPointer();
2882 const int *pt=_nodal_connec->getConstPointer();
2883 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2884 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2887 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2888 throw INTERP_KERNEL::Exception(oss.str().c_str());
2893 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2894 * This method does not throw exception if geometric type \a type is not in \a this.
2895 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2896 * The coordinates array is not considered here.
2898 * \param [in] type the geometric type
2899 * \return cell ids in this having geometric type \a type.
2901 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2906 checkConnectivityFullyDefined();
2907 int nbCells=getNumberOfCells();
2908 int mdim=getMeshDimension();
2909 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2910 if(mdim!=(int)cm.getDimension())
2911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2912 const int *ptI=_nodal_connec_index->getConstPointer();
2913 const int *pt=_nodal_connec->getConstPointer();
2914 for(int i=0;i<nbCells;i++)
2916 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2917 ret->pushBackSilent(i);
2923 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2925 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2927 const int *ptI=_nodal_connec_index->getConstPointer();
2928 const int *pt=_nodal_connec->getConstPointer();
2929 int nbOfCells=getNumberOfCells();
2931 for(int i=0;i<nbOfCells;i++)
2932 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2938 * Returns the nodal connectivity of a given cell.
2939 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2940 * all returned node ids can be used in getCoordinatesOfNode().
2941 * \param [in] cellId - an id of the cell of interest.
2942 * \param [in,out] conn - a vector where the node ids are appended. It is not
2943 * cleared before the appending.
2944 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2946 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2948 const int *ptI=_nodal_connec_index->getConstPointer();
2949 const int *pt=_nodal_connec->getConstPointer();
2950 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2955 std::string MEDCouplingUMesh::simpleRepr() const
2957 static const char msg0[]="No coordinates specified !";
2958 std::ostringstream ret;
2959 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2960 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2962 double tt=getTime(tmpp1,tmpp2);
2963 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2964 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2966 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2968 { ret << " Mesh dimension has not been set or is invalid !"; }
2971 const int spaceDim=getSpaceDimension();
2972 ret << spaceDim << "\nInfo attached on space dimension : ";
2973 for(int i=0;i<spaceDim;i++)
2974 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2978 ret << msg0 << "\n";
2979 ret << "Number of nodes : ";
2981 ret << getNumberOfNodes() << "\n";
2983 ret << msg0 << "\n";
2984 ret << "Number of cells : ";
2985 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2986 ret << getNumberOfCells() << "\n";
2988 ret << "No connectivity specified !" << "\n";
2989 ret << "Cell types present : ";
2990 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2992 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2993 ret << cm.getRepr() << " ";
2999 std::string MEDCouplingUMesh::advancedRepr() const
3001 std::ostringstream ret;
3002 ret << simpleRepr();
3003 ret << "\nCoordinates array : \n___________________\n\n";
3005 _coords->reprWithoutNameStream(ret);
3007 ret << "No array set !\n";
3008 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3009 reprConnectivityOfThisLL(ret);
3014 * This method returns a C++ code that is a dump of \a this.
3015 * This method will throw if this is not fully defined.
3017 std::string MEDCouplingUMesh::cppRepr() const
3019 static const char coordsName[]="coords";
3020 static const char connName[]="conn";
3021 static const char connIName[]="connI";
3022 checkFullyDefined();
3023 std::ostringstream ret; ret << "// coordinates" << std::endl;
3024 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3025 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3026 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3027 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3028 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3029 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3030 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3034 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3036 std::ostringstream ret;
3037 reprConnectivityOfThisLL(ret);
3042 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3043 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3044 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3047 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3048 * 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
3049 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3051 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3053 int mdim=getMeshDimension();
3055 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3056 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3058 bool needToCpyCT=true;
3061 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3069 if(!_nodal_connec_index)
3071 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3076 tmp2=_nodal_connec_index;
3079 ret->setConnectivity(tmp1,tmp2,false);
3084 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3085 ret->setCoords(coords);
3088 ret->setCoords(_coords);
3092 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3094 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3096 int nbOfCells=getNumberOfCells();
3097 const int *c=_nodal_connec->getConstPointer();
3098 const int *ci=_nodal_connec_index->getConstPointer();
3099 for(int i=0;i<nbOfCells;i++)
3101 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3102 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3103 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3108 stream << "Connectivity not defined !\n";
3111 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3113 const int *ptI=_nodal_connec_index->getConstPointer();
3114 const int *pt=_nodal_connec->getConstPointer();
3115 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3116 return ptI[cellId+1]-ptI[cellId]-1;
3118 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3122 * Returns types of cells of the specified part of \a this mesh.
3123 * This method avoids computing sub-mesh explicitely to get its types.
3124 * \param [in] begin - an array of cell ids of interest.
3125 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3126 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3127 * describing the cell types.
3128 * \throw If the coordinates array is not set.
3129 * \throw If the nodal connectivity of cells is not defined.
3130 * \sa getAllGeoTypes()
3132 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3134 checkFullyDefined();
3135 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3136 const int *conn=_nodal_connec->getConstPointer();
3137 const int *connIndex=_nodal_connec_index->getConstPointer();
3138 for(const int *w=begin;w!=end;w++)
3139 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3144 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3145 * a set of types of cells constituting \a this mesh.
3146 * This method is for advanced users having prepared their connectivity before. For
3147 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3148 * \param [in] conn - the nodal connectivity array.
3149 * \param [in] connIndex - the nodal connectivity index array.
3150 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3153 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3155 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3156 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3157 if(isComputingTypes)
3163 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3164 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3166 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3167 _nodal_connec(0),_nodal_connec_index(0),
3168 _types(other._types)
3170 if(other._nodal_connec)
3171 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3172 if(other._nodal_connec_index)
3173 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3176 MEDCouplingUMesh::~MEDCouplingUMesh()
3179 _nodal_connec->decrRef();
3180 if(_nodal_connec_index)
3181 _nodal_connec_index->decrRef();
3185 * Recomputes a set of cell types of \a this mesh. For more info see
3186 * \ref MEDCouplingUMeshNodalConnectivity.
3188 void MEDCouplingUMesh::computeTypes()
3190 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3194 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3196 void MEDCouplingUMesh::checkFullyDefined() const
3198 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3199 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3203 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3205 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3207 if(!_nodal_connec_index || !_nodal_connec)
3208 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3212 * Returns a number of cells constituting \a this mesh.
3213 * \return int - the number of cells in \a this mesh.
3214 * \throw If the nodal connectivity of cells is not defined.
3216 int MEDCouplingUMesh::getNumberOfCells() const
3218 if(_nodal_connec_index)
3219 return _nodal_connec_index->getNumberOfTuples()-1;
3224 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3228 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3229 * mesh. For more info see \ref MEDCouplingMeshesPage.
3230 * \return int - the dimension of \a this mesh.
3231 * \throw If the mesh dimension is not defined using setMeshDimension().
3233 int MEDCouplingUMesh::getMeshDimension() const
3236 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3241 * Returns a length of the nodal connectivity array.
3242 * This method is for test reason. Normally the integer returned is not useable by
3243 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3244 * \return int - the length of the nodal connectivity array.
3246 int MEDCouplingUMesh::getMeshLength() const
3248 return _nodal_connec->getNbOfElems();
3252 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3254 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3256 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3257 tinyInfo.push_back(getMeshDimension());
3258 tinyInfo.push_back(getNumberOfCells());
3260 tinyInfo.push_back(getMeshLength());
3262 tinyInfo.push_back(-1);
3266 * First step of unserialization process.
3268 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3270 return tinyInfo[6]<=0;
3274 * Second step of serialization process.
3275 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3277 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3279 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3281 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3285 * Third and final step of serialization process.
3287 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3289 MEDCouplingPointSet::serialize(a1,a2);
3290 if(getMeshDimension()>-1)
3292 a1=DataArrayInt::New();
3293 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3294 int *ptA1=a1->getPointer();
3295 const int *conn=getNodalConnectivity()->getConstPointer();
3296 const int *index=getNodalConnectivityIndex()->getConstPointer();
3297 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3298 std::copy(conn,conn+getMeshLength(),ptA1);
3305 * Second and final unserialization process.
3306 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3308 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3310 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3311 setMeshDimension(tinyInfo[5]);
3315 const int *recvBuffer=a1->getConstPointer();
3316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3317 myConnecIndex->alloc(tinyInfo[6]+1,1);
3318 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3320 myConnec->alloc(tinyInfo[7],1);
3321 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3322 setConnectivity(myConnec, myConnecIndex);
3327 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3328 * CellIds are given using range specified by a start an end and step.
3330 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3332 checkFullyDefined();
3333 int ncell=getNumberOfCells();
3334 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3335 ret->_mesh_dim=_mesh_dim;
3336 ret->setCoords(_coords);
3337 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3339 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3341 const int *conn=_nodal_connec->getConstPointer();
3342 const int *connIndex=_nodal_connec_index->getConstPointer();
3343 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3345 if(work>=0 && work<ncell)
3347 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3351 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3352 throw INTERP_KERNEL::Exception(oss.str().c_str());
3355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3356 int *newConnPtr=newConn->getPointer();
3357 std::set<INTERP_KERNEL::NormalizedCellType> types;
3359 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3361 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3362 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3364 ret->setConnectivity(newConn,newConnI,false);
3366 ret->copyTinyInfoFrom(this);
3371 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3372 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3373 * The return newly allocated mesh will share the same coordinates as \a this.
3375 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3377 checkConnectivityFullyDefined();
3378 int ncell=getNumberOfCells();
3379 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3380 ret->_mesh_dim=_mesh_dim;
3381 ret->setCoords(_coords);
3382 std::size_t nbOfElemsRet=std::distance(begin,end);
3383 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3385 const int *conn=_nodal_connec->getConstPointer();
3386 const int *connIndex=_nodal_connec_index->getConstPointer();
3388 for(const int *work=begin;work!=end;work++,newNbring++)
3390 if(*work>=0 && *work<ncell)
3391 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3395 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3396 throw INTERP_KERNEL::Exception(oss.str().c_str());
3399 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3400 int *connRetWork=connRet;
3401 std::set<INTERP_KERNEL::NormalizedCellType> types;
3402 for(const int *work=begin;work!=end;work++)
3404 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3405 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3408 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3409 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3410 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3411 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3413 ret->copyTinyInfoFrom(this);
3418 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3420 * For 1D cells, the returned field contains lengths.<br>
3421 * For 2D cells, the returned field contains areas.<br>
3422 * For 3D cells, the returned field contains volumes.
3423 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3424 * orientation, i.e. the volume is always positive.
3425 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3426 * and one time . The caller is to delete this field using decrRef() as it is no
3429 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3431 std::string name="MeasureOfMesh_";
3433 int nbelem=getNumberOfCells();
3434 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3435 field->setName(name);
3436 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3437 array->alloc(nbelem,1);
3438 double *area_vol=array->getPointer();
3439 field->setArray(array) ; array=0;
3440 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3441 field->synchronizeTimeWithMesh();
3442 if(getMeshDimension()!=-1)
3445 INTERP_KERNEL::NormalizedCellType type;
3446 int dim_space=getSpaceDimension();
3447 const double *coords=getCoords()->getConstPointer();
3448 const int *connec=getNodalConnectivity()->getConstPointer();
3449 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3450 for(int iel=0;iel<nbelem;iel++)
3452 ipt=connec_index[iel];
3453 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3454 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);
3457 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3461 area_vol[0]=std::numeric_limits<double>::max();
3463 return field.retn();
3467 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3469 * For 1D cells, the returned array contains lengths.<br>
3470 * For 2D cells, the returned array contains areas.<br>
3471 * For 3D cells, the returned array contains volumes.
3472 * This method avoids building explicitly a part of \a this mesh to perform the work.
3473 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3474 * orientation, i.e. the volume is always positive.
3475 * \param [in] begin - an array of cell ids of interest.
3476 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3477 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3478 * delete this array using decrRef() as it is no more needed.
3480 * \if ENABLE_EXAMPLES
3481 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3482 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3484 * \sa getMeasureField()
3486 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3488 std::string name="PartMeasureOfMesh_";
3490 int nbelem=(int)std::distance(begin,end);
3491 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3492 array->setName(name);
3493 array->alloc(nbelem,1);
3494 double *area_vol=array->getPointer();
3495 if(getMeshDimension()!=-1)
3498 INTERP_KERNEL::NormalizedCellType type;
3499 int dim_space=getSpaceDimension();
3500 const double *coords=getCoords()->getConstPointer();
3501 const int *connec=getNodalConnectivity()->getConstPointer();
3502 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3503 for(const int *iel=begin;iel!=end;iel++)
3505 ipt=connec_index[*iel];
3506 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3507 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3510 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3514 area_vol[0]=std::numeric_limits<double>::max();
3516 return array.retn();
3520 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3521 * \a this one. The returned field contains the dual cell volume for each corresponding
3522 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3523 * the dual mesh in P1 sens of \a this.<br>
3524 * For 1D cells, the returned field contains lengths.<br>
3525 * For 2D cells, the returned field contains areas.<br>
3526 * For 3D cells, the returned field contains volumes.
3527 * This method is useful to check "P1*" conservative interpolators.
3528 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3529 * orientation, i.e. the volume is always positive.
3530 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3531 * nodes and one time. The caller is to delete this array using decrRef() as
3532 * it is no more needed.
3534 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3536 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3537 std::string name="MeasureOnNodeOfMesh_";
3539 int nbNodes=getNumberOfNodes();
3540 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3541 double cst=1./((double)getMeshDimension()+1.);
3542 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3543 array->alloc(nbNodes,1);
3544 double *valsToFill=array->getPointer();
3545 std::fill(valsToFill,valsToFill+nbNodes,0.);
3546 const double *values=tmp->getArray()->getConstPointer();
3547 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3548 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3549 getReverseNodalConnectivity(da,daInd);
3550 const int *daPtr=da->getConstPointer();
3551 const int *daIPtr=daInd->getConstPointer();
3552 for(int i=0;i<nbNodes;i++)
3553 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3554 valsToFill[i]+=cst*values[*cell];
3556 ret->setArray(array);
3561 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3562 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3563 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3564 * and are normalized.
3565 * <br> \a this can be either
3566 * - a 2D mesh in 2D or 3D space or
3567 * - an 1D mesh in 2D space.
3569 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3570 * cells and one time. The caller is to delete this field using decrRef() as
3571 * it is no more needed.
3572 * \throw If the nodal connectivity of cells is not defined.
3573 * \throw If the coordinates array is not set.
3574 * \throw If the mesh dimension is not set.
3575 * \throw If the mesh and space dimension is not as specified above.
3577 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3579 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3580 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3581 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3582 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3583 int nbOfCells=getNumberOfCells();
3584 int nbComp=getMeshDimension()+1;
3585 array->alloc(nbOfCells,nbComp);
3586 double *vals=array->getPointer();
3587 const int *connI=_nodal_connec_index->getConstPointer();
3588 const int *conn=_nodal_connec->getConstPointer();
3589 const double *coords=_coords->getConstPointer();
3590 if(getMeshDimension()==2)
3592 if(getSpaceDimension()==3)
3594 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3595 const double *locPtr=loc->getConstPointer();
3596 for(int i=0;i<nbOfCells;i++,vals+=3)
3598 int offset=connI[i];
3599 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3600 double n=INTERP_KERNEL::norm<3>(vals);
3601 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3606 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3607 const double *isAbsPtr=isAbs->getArray()->begin();
3608 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3609 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3612 else//meshdimension==1
3615 for(int i=0;i<nbOfCells;i++)
3617 int offset=connI[i];
3618 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3619 double n=INTERP_KERNEL::norm<2>(tmp);
3620 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3625 ret->setArray(array);
3627 ret->synchronizeTimeWithSupport();
3632 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3633 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3634 * and are normalized.
3635 * <br> \a this can be either
3636 * - a 2D mesh in 2D or 3D space or
3637 * - an 1D mesh in 2D space.
3639 * This method avoids building explicitly a part of \a this mesh to perform the work.
3640 * \param [in] begin - an array of cell ids of interest.
3641 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3642 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3643 * cells and one time. The caller is to delete this field using decrRef() as
3644 * it is no more needed.
3645 * \throw If the nodal connectivity of cells is not defined.
3646 * \throw If the coordinates array is not set.
3647 * \throw If the mesh dimension is not set.
3648 * \throw If the mesh and space dimension is not as specified above.
3649 * \sa buildOrthogonalField()
3651 * \if ENABLE_EXAMPLES
3652 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3653 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3656 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3658 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3659 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3660 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3661 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3662 std::size_t nbelems=std::distance(begin,end);
3663 int nbComp=getMeshDimension()+1;
3664 array->alloc((int)nbelems,nbComp);
3665 double *vals=array->getPointer();
3666 const int *connI=_nodal_connec_index->getConstPointer();
3667 const int *conn=_nodal_connec->getConstPointer();
3668 const double *coords=_coords->getConstPointer();
3669 if(getMeshDimension()==2)
3671 if(getSpaceDimension()==3)
3673 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3674 const double *locPtr=loc->getConstPointer();
3675 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3677 int offset=connI[*i];
3678 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3679 double n=INTERP_KERNEL::norm<3>(vals);
3680 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3685 for(std::size_t i=0;i<nbelems;i++)
3686 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3689 else//meshdimension==1
3692 for(const int *i=begin;i!=end;i++)
3694 int offset=connI[*i];
3695 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3696 double n=INTERP_KERNEL::norm<2>(tmp);
3697 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3702 ret->setArray(array);
3704 ret->synchronizeTimeWithSupport();
3709 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3710 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3711 * and are \b not normalized.
3712 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3713 * cells and one time. The caller is to delete this field using decrRef() as
3714 * it is no more needed.
3715 * \throw If the nodal connectivity of cells is not defined.
3716 * \throw If the coordinates array is not set.
3717 * \throw If \a this->getMeshDimension() != 1.
3718 * \throw If \a this mesh includes cells of type other than SEG2.
3720 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3722 if(getMeshDimension()!=1)
3723 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3724 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3725 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3726 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3727 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3728 int nbOfCells=getNumberOfCells();
3729 int spaceDim=getSpaceDimension();
3730 array->alloc(nbOfCells,spaceDim);
3731 double *pt=array->getPointer();
3732 const double *coo=getCoords()->getConstPointer();
3733 std::vector<int> conn;
3735 for(int i=0;i<nbOfCells;i++)
3738 getNodeIdsOfCell(i,conn);
3739 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3741 ret->setArray(array);
3743 ret->synchronizeTimeWithSupport();
3748 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3749 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3750 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3751 * from. If a result face is shared by two 3D cells, then the face in included twice in
3753 * \param [in] origin - 3 components of a point defining location of the plane.
3754 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3755 * must be greater than 1e-6.
3756 * \param [in] eps - half-thickness of the plane.
3757 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3758 * producing correspondent 2D cells. The caller is to delete this array
3759 * using decrRef() as it is no more needed.
3760 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3761 * not share the node coordinates array with \a this mesh. The caller is to
3762 * delete this mesh using decrRef() as it is no more needed.
3763 * \throw If the coordinates array is not set.
3764 * \throw If the nodal connectivity of cells is not defined.
3765 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3766 * \throw If magnitude of \a vec is less than 1e-6.
3767 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3768 * \throw If \a this includes quadratic cells.
3770 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3772 checkFullyDefined();
3773 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3774 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3776 if(candidates->empty())
3777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3778 std::vector<int> nodes;
3779 DataArrayInt *cellIds1D=0;
3780 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3781 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3782 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3785 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3786 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3787 revDesc2=0; revDescIndx2=0;
3788 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3789 revDesc1=0; revDescIndx1=0;
3790 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3791 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3793 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3794 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3796 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3797 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3798 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3799 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3800 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3801 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3802 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3803 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3804 if(cellIds2->empty())
3805 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3806 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3807 ret->setCoords(mDesc1->getCoords());
3808 ret->setConnectivity(conn,connI,true);
3809 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3814 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3815 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
3816 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3818 * \param [in] origin - 3 components of a point defining location of the plane.
3819 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3820 * must be greater than 1e-6.
3821 * \param [in] eps - half-thickness of the plane.
3822 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3823 * producing correspondent segments. The caller is to delete this array
3824 * using decrRef() as it is no more needed.
3825 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3826 * mesh in 3D space. This mesh does not share the node coordinates array with
3827 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3829 * \throw If the coordinates array is not set.
3830 * \throw If the nodal connectivity of cells is not defined.
3831 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3832 * \throw If magnitude of \a vec is less than 1e-6.
3833 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3834 * \throw If \a this includes quadratic cells.
3836 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3838 checkFullyDefined();
3839 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3840 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3842 if(candidates->empty())
3843 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3844 std::vector<int> nodes;
3845 DataArrayInt *cellIds1D=0;
3846 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3847 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3851 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3852 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3853 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3856 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3857 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3859 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3860 int ncellsSub=subMesh->getNumberOfCells();
3861 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3862 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3863 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3864 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3867 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3868 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3869 for(int i=0;i<ncellsSub;i++)
3871 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3873 if(cut3DSurf[i].first!=-2)
3875 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3876 connI->pushBackSilent(conn->getNumberOfTuples());
3877 cellIds2->pushBackSilent(i);
3881 int cellId3DSurf=cut3DSurf[i].second;
3882 int offset=nodalI[cellId3DSurf]+1;
3883 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3884 for(int j=0;j<nbOfEdges;j++)
3886 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3887 connI->pushBackSilent(conn->getNumberOfTuples());
3888 cellIds2->pushBackSilent(cellId3DSurf);
3893 if(cellIds2->empty())
3894 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3895 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3896 ret->setCoords(mDesc1->getCoords());
3897 ret->setConnectivity(conn,connI,true);
3898 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3903 * Finds cells whose bounding boxes intersect a given plane.
3904 * \param [in] origin - 3 components of a point defining location of the plane.
3905 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3906 * must be greater than 1e-6.
3907 * \param [in] eps - half-thickness of the plane.
3908 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3909 * cells. The caller is to delete this array using decrRef() as it is no more
3911 * \throw If the coordinates array is not set.
3912 * \throw If the nodal connectivity of cells is not defined.
3913 * \throw If \a this->getSpaceDimension() != 3.
3914 * \throw If magnitude of \a vec is less than 1e-6.
3915 * \sa buildSlice3D()
3917 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3919 checkFullyDefined();
3920 if(getSpaceDimension()!=3)
3921 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3922 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3924 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3926 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3927 double angle=acos(vec[2]/normm);
3928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3932 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3933 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3934 if(normm2/normm>1e-6)
3935 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3936 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3938 mw->getBoundingBox(bbox);
3939 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3940 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3944 getBoundingBox(bbox);
3945 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3946 cellIds=getCellsInBoundingBox(bbox,eps);
3948 return cellIds.retn();
3952 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3953 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3954 * No consideration of coordinate is done by this method.
3955 * 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)
3956 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3958 bool MEDCouplingUMesh::isContiguous1D() const
3960 if(getMeshDimension()!=1)
3961 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3962 int nbCells=getNumberOfCells();
3964 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3965 const int *connI=_nodal_connec_index->getConstPointer();
3966 const int *conn=_nodal_connec->getConstPointer();
3967 int ref=conn[connI[0]+2];
3968 for(int i=1;i<nbCells;i++)
3970 if(conn[connI[i]+1]!=ref)
3972 ref=conn[connI[i]+2];
3978 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3979 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3980 * \param pt reference point of the line
3981 * \param v normalized director vector of the line
3982 * \param eps max precision before throwing an exception
3983 * \param res output of size this->getNumberOfCells
3985 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3987 if(getMeshDimension()!=1)
3988 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3989 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3990 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3991 if(getSpaceDimension()!=3)
3992 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3993 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3994 const double *fPtr=f->getArray()->getConstPointer();
3996 for(int i=0;i<getNumberOfCells();i++)
3998 const double *tmp1=fPtr+3*i;
3999 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4000 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4001 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4002 double n1=INTERP_KERNEL::norm<3>(tmp);
4003 n1/=INTERP_KERNEL::norm<3>(tmp1);
4005 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4007 const double *coo=getCoords()->getConstPointer();
4008 for(int i=0;i<getNumberOfNodes();i++)
4010 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4011 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4012 res[i]=std::accumulate(tmp,tmp+3,0.);
4017 * 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.
4018 * \a this is expected to be a mesh so that its space dimension is equal to its
4019 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4020 * 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).
4022 * 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
4023 * 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).
4024 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4026 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4027 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4029 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4030 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4031 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4032 * \return the positive value of the distance.
4033 * \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
4035 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4037 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4039 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4040 if(meshDim!=spaceDim-1)
4041 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4042 if(meshDim!=2 && meshDim!=1)
4043 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4044 checkFullyDefined();
4045 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4046 { 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()); }
4047 DataArrayInt *ret1=0;
4048 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4049 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4051 cellId=*ret1Safe->begin();
4052 return *ret0->begin();
4056 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4057 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4058 * 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
4059 * 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).
4060 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4062 * \a this is expected to be a mesh so that its space dimension is equal to its
4063 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4064 * 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).
4066 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4067 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4069 * \param [in] pts the list of points in which each tuple represents a point
4070 * \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.
4071 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4072 * \throw if number of components of \a pts is not equal to the space dimension.
4073 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4074 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4076 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4079 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4080 pts->checkAllocated();
4081 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4082 if(meshDim!=spaceDim-1)
4083 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4084 if(meshDim!=2 && meshDim!=1)
4085 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4086 if(pts->getNumberOfComponents()!=spaceDim)
4088 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4089 throw INTERP_KERNEL::Exception(oss.str().c_str());
4091 checkFullyDefined();
4092 int nbCells=getNumberOfCells();
4094 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4095 int nbOfPts=pts->getNumberOfTuples();
4096 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4098 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4099 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4100 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4101 const double *bbox(bboxArr->begin());
4106 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4107 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4109 double x=std::numeric_limits<double>::max();
4110 std::vector<int> elems;
4111 myTree.getMinDistanceOfMax(ptsPtr,x);
4112 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4113 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4119 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4120 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4122 double x=std::numeric_limits<double>::max();
4123 std::vector<int> elems;
4124 myTree.getMinDistanceOfMax(ptsPtr,x);
4125 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4126 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4131 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4133 cellIds=ret1.retn();
4138 * \param [in] pt the start pointer (included) of the coordinates of the point
4139 * \param [in] cellIdsBg the start pointer (included) of cellIds
4140 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4141 * \param [in] nc nodal connectivity
4142 * \param [in] ncI nodal connectivity index
4143 * \param [in,out] ret0 the min distance between \a this and the external input point
4144 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4145 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4147 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)
4150 ret0=std::numeric_limits<double>::max();
4151 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4153 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4155 case INTERP_KERNEL::NORM_TRI3:
4157 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4159 { ret0=tmp; cellId=*zeCell; }
4162 case INTERP_KERNEL::NORM_QUAD4:
4163 case INTERP_KERNEL::NORM_POLYGON:
4165 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4167 { ret0=tmp; cellId=*zeCell; }
4171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4177 * \param [in] pt the start pointer (included) of the coordinates of the point
4178 * \param [in] cellIdsBg the start pointer (included) of cellIds
4179 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4180 * \param [in] nc nodal connectivity
4181 * \param [in] ncI nodal connectivity index
4182 * \param [in,out] ret0 the min distance between \a this and the external input point
4183 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4184 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4186 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)
4189 ret0=std::numeric_limits<double>::max();
4190 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4192 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4194 case INTERP_KERNEL::NORM_SEG2:
4196 std::size_t uselessEntry=0;
4197 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4200 { ret0=tmp; cellId=*zeCell; }
4204 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4210 * Finds cells in contact with a ball (i.e. a point with precision).
4211 * 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.
4212 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4214 * \warning This method is suitable if the caller intends to evaluate only one
4215 * point, for more points getCellsContainingPoints() is recommended as it is
4217 * \param [in] pos - array of coordinates of the ball central point.
4218 * \param [in] eps - ball radius.
4219 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4220 * if there are no such cells.
4221 * \throw If the coordinates array is not set.
4222 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4224 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4226 std::vector<int> elts;
4227 getCellsContainingPoint(pos,eps,elts);
4230 return elts.front();
4234 * Finds cells in contact with a ball (i.e. a point with precision).
4235 * 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.
4236 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4237 * \warning This method is suitable if the caller intends to evaluate only one
4238 * point, for more points getCellsContainingPoints() is recommended as it is
4240 * \param [in] pos - array of coordinates of the ball central point.
4241 * \param [in] eps - ball radius.
4242 * \param [out] elts - vector returning ids of the found cells. It is cleared
4243 * before inserting ids.
4244 * \throw If the coordinates array is not set.
4245 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4247 * \if ENABLE_EXAMPLES
4248 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4249 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4252 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4255 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4256 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4261 namespace ParaMEDMEM
4263 template<const int SPACEDIMM>
4267 static const int MY_SPACEDIM=SPACEDIMM;
4268 static const int MY_MESHDIM=8;
4269 typedef int MyConnType;
4270 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4272 // useless, but for windows compilation ...
4273 const double* getCoordinatesPtr() const { return 0; }
4274 const int* getConnectivityPtr() const { return 0; }
4275 const int* getConnectivityIndexPtr() const { return 0; }
4276 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4280 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4282 INTERP_KERNEL::Edge *ret(0);
4283 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]));
4284 m[n0]=bg[0]; m[n1]=bg[1];
4287 case INTERP_KERNEL::NORM_SEG2:
4289 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4292 case INTERP_KERNEL::NORM_SEG3:
4294 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4295 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4296 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4297 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4298 bool colinearity(inters.areColinears());
4299 delete e1; delete e2;
4301 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4303 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4307 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4312 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4314 INTERP_KERNEL::Edge *ret=0;
4317 case INTERP_KERNEL::NORM_SEG2:
4319 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4322 case INTERP_KERNEL::NORM_SEG3:
4324 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4325 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4326 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4327 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4328 bool colinearity=inters.areColinears();
4329 delete e1; delete e2;
4331 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4333 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4334 mapp2[bg[2]].second=false;
4338 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4344 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4345 * the global mesh 'mDesc'.
4346 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4347 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4349 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4350 std::map<INTERP_KERNEL::Node *,int>& mapp)
4353 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.
4354 const double *coo=mDesc->getCoords()->getConstPointer();
4355 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4356 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4358 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4359 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4360 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4362 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4363 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4365 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4366 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4368 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4369 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4371 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4373 if((*it2).second.second)
4374 mapp[(*it2).second.first]=(*it2).first;
4375 ((*it2).second.first)->decrRef();
4380 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4384 int locId=nodeId-offset2;
4385 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4389 int locId=nodeId-offset1;
4390 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4392 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4396 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4398 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4399 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4400 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4402 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4404 int eltId1=abs(*desc1)-1;
4405 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4407 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4408 if(it==mappRev.end())
4410 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4421 template<int SPACEDIM>
4422 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4423 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4425 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4426 int *eltsIndexPtr(eltsIndex->getPointer());
4427 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4428 const double *bbox(bboxArr->begin());
4429 int nbOfCells=getNumberOfCells();
4430 const int *conn=_nodal_connec->getConstPointer();
4431 const int *connI=_nodal_connec_index->getConstPointer();
4432 double bb[2*SPACEDIM];
4433 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4434 for(int i=0;i<nbOfPoints;i++)
4436 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4437 for(int j=0;j<SPACEDIM;j++)
4439 bb[2*j]=pos[SPACEDIM*i+j];
4440 bb[2*j+1]=pos[SPACEDIM*i+j];
4442 std::vector<int> candidates;
4443 myTree.getIntersectingElems(bb,candidates);
4444 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4446 int sz(connI[(*iter)+1]-connI[*iter]-1);
4447 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4449 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4450 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4455 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4456 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4457 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4458 INTERP_KERNEL::QuadraticPolygon *pol(0);
4459 for(int j=0;j<sz;j++)
4461 int nodeId(conn[connI[*iter]+1+j]);
4462 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4464 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4465 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4467 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4468 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4469 double a(0.),b(0.),c(0.);
4470 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4471 status=pol->isInOrOut2(n);
4472 delete pol; n->decrRef();
4476 eltsIndexPtr[i+1]++;
4477 elts->pushBackSilent(*iter);
4483 * Finds cells in contact with several balls (i.e. points with precision).
4484 * This method is an extension of getCellContainingPoint() and
4485 * getCellsContainingPoint() for the case of multiple points.
4486 * 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.
4487 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4488 * \param [in] pos - an array of coordinates of points in full interlace mode :
4489 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4490 * this->getSpaceDimension() * \a nbOfPoints
4491 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4492 * \param [in] eps - radius of balls (i.e. the precision).
4493 * \param [out] elts - vector returning ids of found cells.
4494 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4495 * dividing cell ids in \a elts into groups each referring to one
4496 * point. Its every element (except the last one) is an index pointing to the
4497 * first id of a group of cells. For example cells in contact with the *i*-th
4498 * point are described by following range of indices:
4499 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4500 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4501 * Number of cells in contact with the *i*-th point is
4502 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4503 * \throw If the coordinates array is not set.
4504 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4506 * \if ENABLE_EXAMPLES
4507 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4508 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4511 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4512 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4514 int spaceDim=getSpaceDimension();
4515 int mDim=getMeshDimension();
4520 const double *coords=_coords->getConstPointer();
4521 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4528 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4530 else if(spaceDim==2)
4534 const double *coords=_coords->getConstPointer();
4535 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4538 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4540 else if(spaceDim==1)
4544 const double *coords=_coords->getConstPointer();
4545 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4548 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4551 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4555 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4556 * least two its edges intersect each other anywhere except their extremities. An
4557 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4558 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4559 * cleared before filling in.
4560 * \param [in] eps - precision.
4561 * \throw If \a this->getMeshDimension() != 2.
4562 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4564 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4566 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4567 if(getMeshDimension()!=2)
4568 throw INTERP_KERNEL::Exception(msg);
4569 int spaceDim=getSpaceDimension();
4570 if(spaceDim!=2 && spaceDim!=3)
4571 throw INTERP_KERNEL::Exception(msg);
4572 const int *conn=_nodal_connec->getConstPointer();
4573 const int *connI=_nodal_connec_index->getConstPointer();
4574 int nbOfCells=getNumberOfCells();
4575 std::vector<double> cell2DinS2;
4576 for(int i=0;i<nbOfCells;i++)
4578 int offset=connI[i];
4579 int nbOfNodesForCell=connI[i+1]-offset-1;
4580 if(nbOfNodesForCell<=3)
4582 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4583 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4584 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4591 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4593 * 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.
4594 * 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.
4596 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4597 * This convex envelop is computed using Jarvis march algorithm.
4598 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4599 * 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)
4600 * 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.
4602 * \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.
4603 * \sa MEDCouplingUMesh::colinearize2D
4605 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4607 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4608 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4609 checkFullyDefined();
4610 const double *coords=getCoords()->getConstPointer();
4611 int nbOfCells=getNumberOfCells();
4612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4613 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4614 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4615 int *workIndexOut=nodalConnecIndexOut->getPointer();
4617 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4618 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4619 std::set<INTERP_KERNEL::NormalizedCellType> types;
4620 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4621 isChanged->alloc(0,1);
4622 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4624 int pos=nodalConnecOut->getNumberOfTuples();
4625 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4626 isChanged->pushBackSilent(i);
4627 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4628 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4630 if(isChanged->empty())
4632 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4634 return isChanged.retn();
4638 * This method is \b NOT const because it can modify \a this.
4639 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4640 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4641 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4642 * \b 1 for translation and rotation around point of 'mesh1D'.
4643 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4645 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4647 checkFullyDefined();
4648 mesh1D->checkFullyDefined();
4649 if(!mesh1D->isContiguous1D())
4650 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4651 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4652 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4653 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4654 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4655 if(mesh1D->getMeshDimension()!=1)
4656 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4658 if(isPresenceOfQuadratic())
4660 if(mesh1D->isFullyQuadratic())
4663 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4665 int oldNbOfNodes(getNumberOfNodes());
4666 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4671 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4676 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4680 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4682 setCoords(newCoords);
4683 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4689 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4690 * If it is not the case an exception will be thrown.
4691 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4692 * intersection of plane defined by ('origin','vec').
4693 * This method has one in/out parameter : 'cut3DCurve'.
4694 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4695 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4696 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4697 * This method will throw an exception if \a this contains a non linear segment.
4699 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4701 checkFullyDefined();
4702 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4704 int ncells=getNumberOfCells();
4705 int nnodes=getNumberOfNodes();
4706 double vec2[3],vec3[3],vec4[3];
4707 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4710 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4711 const int *conn=_nodal_connec->getConstPointer();
4712 const int *connI=_nodal_connec_index->getConstPointer();
4713 const double *coo=_coords->getConstPointer();
4714 std::vector<double> addCoo;
4715 for(int i=0;i<ncells;i++)
4717 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4719 if(cut3DCurve[i]==-2)
4721 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4722 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];
4723 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4724 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4725 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4727 const double *st2=coo+3*st;
4728 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4729 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]));
4730 if(pos>eps && pos<1-eps)
4732 int nNode=((int)addCoo.size())/3;
4733 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4734 addCoo.insert(addCoo.end(),vec4,vec4+3);
4735 cut3DCurve[i]=nnodes+nNode;
4741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4745 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4746 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4747 coo2->alloc(newNbOfNodes,3);
4748 double *tmp=coo2->getPointer();
4749 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4750 std::copy(addCoo.begin(),addCoo.end(),tmp);
4751 DataArrayDouble::SetArrayIn(coo2,_coords);
4756 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4757 * \param mesh1D is the input 1D mesh used for translation computation.
4758 * \return newCoords new coords filled by this method.
4760 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4762 int oldNbOfNodes=getNumberOfNodes();
4763 int nbOf1DCells=mesh1D->getNumberOfCells();
4764 int spaceDim=getSpaceDimension();
4765 DataArrayDouble *ret=DataArrayDouble::New();
4766 std::vector<bool> isQuads;
4767 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4768 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4769 double *retPtr=ret->getPointer();
4770 const double *coords=getCoords()->getConstPointer();
4771 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4773 std::vector<double> c;
4777 for(int i=0;i<nbOf1DCells;i++)
4780 mesh1D->getNodeIdsOfCell(i,v);
4782 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4783 mesh1D->getCoordinatesOfNode(v[0],c);
4784 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4785 for(int j=0;j<oldNbOfNodes;j++)
4786 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4790 mesh1D->getCoordinatesOfNode(v[1],c);
4791 mesh1D->getCoordinatesOfNode(v[0],c);
4792 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4793 for(int j=0;j<oldNbOfNodes;j++)
4794 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4797 ret->copyStringInfoFrom(*getCoords());
4802 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4803 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4804 * \return newCoords new coords filled by this method.
4806 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4808 if(mesh1D->getSpaceDimension()==2)
4809 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4810 if(mesh1D->getSpaceDimension()==3)
4811 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4812 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4816 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4817 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4818 * \return newCoords new coords filled by this method.
4820 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4823 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4824 int oldNbOfNodes=getNumberOfNodes();
4825 int nbOf1DCells=mesh1D->getNumberOfCells();
4827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4828 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4829 int nbOfLevsInVec=nbOf1DCells+1;
4830 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4831 double *retPtr=ret->getPointer();
4832 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4833 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4834 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4835 tmp->setCoords(tmp2);
4836 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4837 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4838 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4839 for(int i=1;i<nbOfLevsInVec;i++)
4841 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4842 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4843 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4844 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4845 tmp->translate(vec);
4846 double tmp3[2],radius,alpha,alpha0;
4847 const double *p0=i+1<nbOfLevsInVec?begin:third;
4848 const double *p1=i+1<nbOfLevsInVec?end:begin;
4849 const double *p2=i+1<nbOfLevsInVec?third:end;
4850 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4851 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]);
4852 double angle=acos(cosangle/(radius*radius));
4853 tmp->rotate(end,0,angle);
4854 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4860 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4861 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4862 * \return newCoords new coords filled by this method.
4864 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4867 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4868 int oldNbOfNodes=getNumberOfNodes();
4869 int nbOf1DCells=mesh1D->getNumberOfCells();
4871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4872 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4873 int nbOfLevsInVec=nbOf1DCells+1;
4874 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4875 double *retPtr=ret->getPointer();
4876 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4877 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4878 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4879 tmp->setCoords(tmp2);
4880 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4881 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4882 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4883 for(int i=1;i<nbOfLevsInVec;i++)
4885 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4886 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4887 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4888 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4889 tmp->translate(vec);
4890 double tmp3[2],radius,alpha,alpha0;
4891 const double *p0=i+1<nbOfLevsInVec?begin:third;
4892 const double *p1=i+1<nbOfLevsInVec?end:begin;
4893 const double *p2=i+1<nbOfLevsInVec?third:end;
4894 double vecPlane[3]={
4895 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4896 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4897 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4899 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4902 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4903 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4904 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4906 double c2=cos(asin(s2));
4908 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4909 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4910 {-vec2[1]*s2, vec2[0]*s2, c2}
4912 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]};
4913 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]};
4914 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]};
4915 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4916 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]);
4917 double angle=acos(cosangle/(radius*radius));
4918 tmp->rotate(end,vecPlane,angle);
4920 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4926 * This method is private because not easy to use for end user. This method is const contrary to
4927 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4928 * the coords sorted slice by slice.
4929 * \param isQuad specifies presence of quadratic cells.
4931 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4933 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4934 int nbOf2DCells(getNumberOfCells());
4935 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4936 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4937 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4939 newConnI->alloc(nbOf3DCells+1,1);
4940 int *newConnIPtr(newConnI->getPointer());
4942 std::vector<int> newc;
4943 for(int j=0;j<nbOf2DCells;j++)
4945 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4946 *newConnIPtr++=(int)newc.size();
4948 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4949 int *newConnPtr(newConn->getPointer());
4950 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4951 newConnIPtr=newConnI->getPointer();
4952 for(int iz=0;iz<nbOf1DCells;iz++)
4955 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4956 const int *posOfTypeOfCell(newConnIPtr);
4957 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4959 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4960 if(icell!=*posOfTypeOfCell)
4963 *newConnPtr=(*iter)+iz*deltaPerLev;
4974 ret->setConnectivity(newConn,newConnI,true);
4975 ret->setCoords(getCoords());
4980 * Checks if \a this mesh is constituted by only quadratic cells.
4981 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4982 * \throw If the coordinates array is not set.
4983 * \throw If the nodal connectivity of cells is not defined.
4985 bool MEDCouplingUMesh::isFullyQuadratic() const
4987 checkFullyDefined();
4989 int nbOfCells=getNumberOfCells();
4990 for(int i=0;i<nbOfCells && ret;i++)
4992 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4993 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4994 ret=cm.isQuadratic();
5000 * Checks if \a this mesh includes any quadratic cell.
5001 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5002 * \throw If the coordinates array is not set.
5003 * \throw If the nodal connectivity of cells is not defined.
5005 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5007 checkFullyDefined();
5009 int nbOfCells=getNumberOfCells();
5010 for(int i=0;i<nbOfCells && !ret;i++)
5012 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5013 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5014 ret=cm.isQuadratic();
5020 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5021 * this mesh, it remains unchanged.
5022 * \throw If the coordinates array is not set.
5023 * \throw If the nodal connectivity of cells is not defined.
5025 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5027 checkFullyDefined();
5028 int nbOfCells=getNumberOfCells();
5030 const int *iciptr=_nodal_connec_index->getConstPointer();
5031 for(int i=0;i<nbOfCells;i++)
5033 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5034 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5035 if(cm.isQuadratic())
5037 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5038 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5039 if(!cml.isDynamic())
5040 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5042 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5049 const int *icptr=_nodal_connec->getConstPointer();
5050 newConn->alloc(getMeshLength()-delta,1);
5051 newConnI->alloc(nbOfCells+1,1);
5052 int *ocptr=newConn->getPointer();
5053 int *ociptr=newConnI->getPointer();
5056 for(int i=0;i<nbOfCells;i++,ociptr++)
5058 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5059 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5060 if(!cm.isQuadratic())
5062 _types.insert(type);
5063 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5064 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5068 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5069 _types.insert(typel);
5070 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5071 int newNbOfNodes=cml.getNumberOfNodes();
5073 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5074 *ocptr++=(int)typel;
5075 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5076 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5079 setConnectivity(newConn,newConnI,false);
5083 * This method converts all linear cell in \a this to quadratic one.
5084 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5085 * 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)
5086 * 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.
5087 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5088 * end of the existing coordinates.
5090 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5091 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5092 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5094 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5096 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5098 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5100 DataArrayInt *conn=0,*connI=0;
5101 DataArrayDouble *coords=0;
5102 std::set<INTERP_KERNEL::NormalizedCellType> types;
5103 checkFullyDefined();
5104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5105 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5106 int meshDim=getMeshDimension();
5107 switch(conversionType)
5113 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5114 connSafe=conn; connISafe=connI; coordsSafe=coords;
5117 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5118 connSafe=conn; connISafe=connI; coordsSafe=coords;
5121 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5122 connSafe=conn; connISafe=connI; coordsSafe=coords;
5125 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5133 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5134 connSafe=conn; connISafe=connI; coordsSafe=coords;
5137 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5138 connSafe=conn; connISafe=connI; coordsSafe=coords;
5141 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5142 connSafe=conn; connISafe=connI; coordsSafe=coords;
5145 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5150 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5152 setConnectivity(connSafe,connISafe,false);
5154 setCoords(coordsSafe);
5160 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5161 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5162 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5163 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5164 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5165 * This method can be seen as the opposite method of colinearize2D.
5166 * 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
5167 * to avoid to modify the numbering of existing nodes.
5169 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5170 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5171 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5172 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5173 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5174 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5175 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5177 * \sa buildDescendingConnectivity2
5179 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5180 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5182 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5183 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5184 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5185 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5187 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5188 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5189 //DataArrayInt *out0(0),*outi0(0);
5190 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5191 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5192 //out0s=out0s->buildUnique(); out0s->sort(true);
5197 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5198 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5199 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5201 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5203 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5204 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5207 int nbOfCells=getNumberOfCells();
5208 int nbOfNodes=getNumberOfNodes();
5209 const int *cPtr=_nodal_connec->getConstPointer();
5210 const int *icPtr=_nodal_connec_index->getConstPointer();
5211 int lastVal=0,offset=nbOfNodes;
5212 for(int i=0;i<nbOfCells;i++,icPtr++)
5214 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5215 if(type==INTERP_KERNEL::NORM_SEG2)
5217 types.insert(INTERP_KERNEL::NORM_SEG3);
5218 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5219 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5220 newConn->pushBackSilent(offset++);
5222 newConnI->pushBackSilent(lastVal);
5223 ret->pushBackSilent(i);
5228 lastVal+=(icPtr[1]-icPtr[0]);
5229 newConnI->pushBackSilent(lastVal);
5230 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5233 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5234 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5238 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
5240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5244 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5245 DataArrayInt *conn1D=0,*conn1DI=0;
5246 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5247 DataArrayDouble *coordsTmp=0;
5248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5249 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5251 const int *c1DPtr=conn1D->begin();
5252 const int *c1DIPtr=conn1DI->begin();
5253 int nbOfCells=getNumberOfCells();
5254 const int *cPtr=_nodal_connec->getConstPointer();
5255 const int *icPtr=_nodal_connec_index->getConstPointer();
5257 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5259 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5260 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5261 if(!cm.isQuadratic())
5263 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5264 types.insert(typ2); newConn->pushBackSilent(typ2);
5265 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5266 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5267 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5268 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5269 newConnI->pushBackSilent(lastVal);
5270 ret->pushBackSilent(i);
5275 lastVal+=(icPtr[1]-icPtr[0]);
5276 newConnI->pushBackSilent(lastVal);
5277 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5280 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5285 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5286 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5287 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5289 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5292 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5293 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5296 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5299 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5303 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5305 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5306 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5307 DataArrayInt *conn1D=0,*conn1DI=0;
5308 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5309 DataArrayDouble *coordsTmp=0;
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5311 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5313 const int *c1DPtr=conn1D->begin();
5314 const int *c1DIPtr=conn1DI->begin();
5315 int nbOfCells=getNumberOfCells();
5316 const int *cPtr=_nodal_connec->getConstPointer();
5317 const int *icPtr=_nodal_connec_index->getConstPointer();
5318 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5319 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5321 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5322 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5323 if(!cm.isQuadratic())
5325 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5326 types.insert(typ2); newConn->pushBackSilent(typ2);
5327 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5328 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5329 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5330 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5331 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5332 newConnI->pushBackSilent(lastVal);
5333 ret->pushBackSilent(i);
5338 lastVal+=(icPtr[1]-icPtr[0]);
5339 newConnI->pushBackSilent(lastVal);
5340 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5343 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5344 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5349 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5350 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5351 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5353 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5357 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5360 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5363 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5365 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5367 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5371 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5372 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5373 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5374 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5375 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5378 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5380 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5382 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5383 int nbOfCells=getNumberOfCells();
5384 const int *cPtr=_nodal_connec->getConstPointer();
5385 const int *icPtr=_nodal_connec_index->getConstPointer();
5386 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5387 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5389 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5390 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5391 if(!cm.isQuadratic())
5393 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5394 if(typ2==INTERP_KERNEL::NORM_ERROR)
5396 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5397 throw INTERP_KERNEL::Exception(oss.str().c_str());
5399 types.insert(typ2); newConn->pushBackSilent(typ2);
5400 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5401 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5402 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5403 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5405 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5406 int tmpPos=newConn->getNumberOfTuples();
5407 newConn->pushBackSilent(nodeId2);
5408 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5410 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5411 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5412 newConnI->pushBackSilent(lastVal);
5413 ret->pushBackSilent(i);
5418 lastVal+=(icPtr[1]-icPtr[0]);
5419 newConnI->pushBackSilent(lastVal);
5420 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5423 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5425 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5426 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5427 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5428 int *c=newConn->getPointer();
5429 const int *cI(newConnI->begin());
5430 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5431 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5432 offset=coordsTmp2Safe->getNumberOfTuples();
5433 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5434 c[cI[(*elt)+1]-1]+=offset;
5435 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5440 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5441 * so that the number of cells remains the same. Quadratic faces are converted to
5442 * polygons. This method works only for 2D meshes in
5443 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5444 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5445 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5446 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5447 * a polylinized edge constituting the input polygon.
5448 * \throw If the coordinates array is not set.
5449 * \throw If the nodal connectivity of cells is not defined.
5450 * \throw If \a this->getMeshDimension() != 2.
5451 * \throw If \a this->getSpaceDimension() != 2.
5453 void MEDCouplingUMesh::tessellate2D(double eps)
5455 checkFullyDefined();
5456 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5457 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5458 double epsa=fabs(eps);
5459 if(epsa<std::numeric_limits<double>::min())
5460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5465 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5466 revDesc1=0; revDescIndx1=0;
5467 mDesc->tessellate2DCurve(eps);
5468 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5469 setCoords(mDesc->getCoords());
5473 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5474 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5475 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5476 * a sub-divided edge.
5477 * \throw If the coordinates array is not set.
5478 * \throw If the nodal connectivity of cells is not defined.
5479 * \throw If \a this->getMeshDimension() != 1.
5480 * \throw If \a this->getSpaceDimension() != 2.
5482 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5484 checkFullyDefined();
5485 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5486 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5487 double epsa=fabs(eps);
5488 if(epsa<std::numeric_limits<double>::min())
5489 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5490 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5491 int nbCells=getNumberOfCells();
5492 int nbNodes=getNumberOfNodes();
5493 const int *conn=_nodal_connec->getConstPointer();
5494 const int *connI=_nodal_connec_index->getConstPointer();
5495 const double *coords=_coords->getConstPointer();
5496 std::vector<double> addCoo;
5497 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5498 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5499 newConnI->alloc(nbCells+1,1);
5500 int *newConnIPtr=newConnI->getPointer();
5503 INTERP_KERNEL::Node *tmp2[3];
5504 std::set<INTERP_KERNEL::NormalizedCellType> types;
5505 for(int i=0;i<nbCells;i++,newConnIPtr++)
5507 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5508 if(cm.isQuadratic())
5509 {//assert(connI[i+1]-connI[i]-1==3)
5510 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5511 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5512 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5513 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5514 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5517 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5518 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5520 newConnIPtr[1]=(int)newConn.size();
5524 types.insert(INTERP_KERNEL::NORM_SEG2);
5525 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5526 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5527 newConnIPtr[1]=newConnIPtr[0]+3;
5532 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5533 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5534 newConnIPtr[1]=newConnIPtr[0]+3;
5537 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5540 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5541 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5542 newConnArr->alloc((int)newConn.size(),1);
5543 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5544 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5545 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5546 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5547 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5548 std::copy(addCoo.begin(),addCoo.end(),work);
5549 DataArrayDouble::SetArrayIn(newCoords,_coords);
5554 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5555 * In addition, returns an array mapping new cells to old ones. <br>
5556 * This method typically increases the number of cells in \a this mesh
5557 * but the number of nodes remains \b unchanged.
5558 * That's why the 3D splitting policies
5559 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5560 * \param [in] policy - specifies a pattern used for splitting.
5561 * The semantic of \a policy is:
5562 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5563 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5564 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5565 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5568 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5569 * an id of old cell producing it. The caller is to delete this array using
5570 * decrRef() as it is no more needed.
5572 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5573 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5574 * and \a this->getMeshDimension() != 3.
5575 * \throw If \a policy is not one of the four discussed above.
5576 * \throw If the nodal connectivity of cells is not defined.
5577 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5579 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5584 return simplexizePol0();
5586 return simplexizePol1();
5587 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5588 return simplexizePlanarFace5();
5589 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5590 return simplexizePlanarFace6();
5592 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)");
5597 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5598 * - 1D: INTERP_KERNEL::NORM_SEG2
5599 * - 2D: INTERP_KERNEL::NORM_TRI3
5600 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5602 * This method is useful for users that need to use P1 field services as
5603 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5604 * All these methods need mesh support containing only simplex cells.
5605 * \return bool - \c true if there are only simplex cells in \a this mesh.
5606 * \throw If the coordinates array is not set.
5607 * \throw If the nodal connectivity of cells is not defined.
5608 * \throw If \a this->getMeshDimension() < 1.
5610 bool MEDCouplingUMesh::areOnlySimplexCells() const
5612 checkFullyDefined();
5613 int mdim=getMeshDimension();
5614 if(mdim<1 || mdim>3)
5615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5616 int nbCells=getNumberOfCells();
5617 const int *conn=_nodal_connec->getConstPointer();
5618 const int *connI=_nodal_connec_index->getConstPointer();
5619 for(int i=0;i<nbCells;i++)
5621 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5629 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5631 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5633 checkConnectivityFullyDefined();
5634 if(getMeshDimension()!=2)
5635 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5636 int nbOfCells=getNumberOfCells();
5637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5638 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5639 ret->alloc(nbOfCells+nbOfCutCells,1);
5640 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5641 int *retPt=ret->getPointer();
5642 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5644 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5645 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5646 int *pt=newConn->getPointer();
5647 int *ptI=newConnI->getPointer();
5649 const int *oldc=_nodal_connec->getConstPointer();
5650 const int *ci=_nodal_connec_index->getConstPointer();
5651 for(int i=0;i<nbOfCells;i++,ci++)
5653 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5655 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5656 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5657 pt=std::copy(tmp,tmp+8,pt);
5666 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5667 ptI[1]=ptI[0]+ci[1]-ci[0];
5672 _nodal_connec->decrRef();
5673 _nodal_connec=newConn.retn();
5674 _nodal_connec_index->decrRef();
5675 _nodal_connec_index=newConnI.retn();
5682 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5684 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5686 checkConnectivityFullyDefined();
5687 if(getMeshDimension()!=2)
5688 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5689 int nbOfCells=getNumberOfCells();
5690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5691 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5692 ret->alloc(nbOfCells+nbOfCutCells,1);
5693 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5694 int *retPt=ret->getPointer();
5695 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5696 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5697 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5698 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5699 int *pt=newConn->getPointer();
5700 int *ptI=newConnI->getPointer();
5702 const int *oldc=_nodal_connec->getConstPointer();
5703 const int *ci=_nodal_connec_index->getConstPointer();
5704 for(int i=0;i<nbOfCells;i++,ci++)
5706 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5708 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5709 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5710 pt=std::copy(tmp,tmp+8,pt);
5719 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5720 ptI[1]=ptI[0]+ci[1]-ci[0];
5725 _nodal_connec->decrRef();
5726 _nodal_connec=newConn.retn();
5727 _nodal_connec_index->decrRef();
5728 _nodal_connec_index=newConnI.retn();
5735 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5737 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5739 checkConnectivityFullyDefined();
5740 if(getMeshDimension()!=3)
5741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5742 int nbOfCells=getNumberOfCells();
5743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5744 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5745 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5746 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5747 int *retPt=ret->getPointer();
5748 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5750 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5751 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5752 int *pt=newConn->getPointer();
5753 int *ptI=newConnI->getPointer();
5755 const int *oldc=_nodal_connec->getConstPointer();
5756 const int *ci=_nodal_connec_index->getConstPointer();
5757 for(int i=0;i<nbOfCells;i++,ci++)
5759 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5761 for(int j=0;j<5;j++,pt+=5,ptI++)
5763 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5764 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];
5771 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5772 ptI[1]=ptI[0]+ci[1]-ci[0];
5777 _nodal_connec->decrRef();
5778 _nodal_connec=newConn.retn();
5779 _nodal_connec_index->decrRef();
5780 _nodal_connec_index=newConnI.retn();
5787 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5789 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5791 checkConnectivityFullyDefined();
5792 if(getMeshDimension()!=3)
5793 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5794 int nbOfCells=getNumberOfCells();
5795 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5796 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5797 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5798 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5799 int *retPt=ret->getPointer();
5800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5801 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5802 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5803 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5804 int *pt=newConn->getPointer();
5805 int *ptI=newConnI->getPointer();
5807 const int *oldc=_nodal_connec->getConstPointer();
5808 const int *ci=_nodal_connec_index->getConstPointer();
5809 for(int i=0;i<nbOfCells;i++,ci++)
5811 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5813 for(int j=0;j<6;j++,pt+=5,ptI++)
5815 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5816 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];
5823 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5824 ptI[1]=ptI[0]+ci[1]-ci[0];
5829 _nodal_connec->decrRef();
5830 _nodal_connec=newConn.retn();
5831 _nodal_connec_index->decrRef();
5832 _nodal_connec_index=newConnI.retn();
5839 * 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.
5840 * This method completly ignore coordinates.
5841 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5842 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5843 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5844 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5846 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5848 checkFullyDefined();
5849 if(getMeshDimension()!=2)
5850 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5851 int nbOfCells=getNumberOfCells();
5852 int *connI=_nodal_connec_index->getPointer();
5854 for(int i=0;i<nbOfCells;i++,connI++)
5856 int offset=descIndex[i];
5857 int nbOfEdges=descIndex[i+1]-offset;
5859 bool ddirect=desc[offset+nbOfEdges-1]>0;
5860 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5861 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5862 for(int j=0;j<nbOfEdges;j++)
5864 bool direct=desc[offset+j]>0;
5865 int edgeId=std::abs(desc[offset+j])-1;
5866 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5868 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5869 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5870 int ref2=direct?id1:id2;
5873 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5874 newConnLgth+=nbOfSubNodes-1;
5879 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5880 throw INTERP_KERNEL::Exception(oss.str().c_str());
5885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5888 newConnLgth++;//+1 is for cell type
5889 connI[1]=newConnLgth;
5892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5893 newConn->alloc(newConnLgth,1);
5894 int *work=newConn->getPointer();
5895 for(int i=0;i<nbOfCells;i++)
5897 *work++=INTERP_KERNEL::NORM_POLYGON;
5898 int offset=descIndex[i];
5899 int nbOfEdges=descIndex[i+1]-offset;
5900 for(int j=0;j<nbOfEdges;j++)
5902 bool direct=desc[offset+j]>0;
5903 int edgeId=std::abs(desc[offset+j])-1;
5905 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5908 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5909 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5910 work=std::copy(it,it+nbOfSubNodes-1,work);
5914 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5917 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5921 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5922 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5923 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5924 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5925 * so it can be useful to call mergeNodes() before calling this method.
5926 * \throw If \a this->getMeshDimension() <= 1.
5927 * \throw If the coordinates array is not set.
5928 * \throw If the nodal connectivity of cells is not defined.
5930 void MEDCouplingUMesh::convertDegeneratedCells()
5932 checkFullyDefined();
5933 if(getMeshDimension()<=1)
5934 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5935 int nbOfCells=getNumberOfCells();
5938 int initMeshLgth=getMeshLength();
5939 int *conn=_nodal_connec->getPointer();
5940 int *index=_nodal_connec_index->getPointer();
5944 for(int i=0;i<nbOfCells;i++)
5946 lgthOfCurCell=index[i+1]-posOfCurCell;
5947 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5949 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5950 conn+newPos+1,newLgth);
5951 conn[newPos]=newType;
5953 posOfCurCell=index[i+1];
5956 if(newPos!=initMeshLgth)
5957 _nodal_connec->reAlloc(newPos);
5962 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5963 * A cell is considered to be oriented correctly if an angle between its
5964 * normal vector and a given vector is less than \c PI / \c 2.
5965 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5967 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5969 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5970 * is not cleared before filling in.
5971 * \throw If \a this->getMeshDimension() != 2.
5972 * \throw If \a this->getSpaceDimension() != 3.
5974 * \if ENABLE_EXAMPLES
5975 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5976 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5979 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5981 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5982 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5983 int nbOfCells=getNumberOfCells();
5984 const int *conn=_nodal_connec->getConstPointer();
5985 const int *connI=_nodal_connec_index->getConstPointer();
5986 const double *coordsPtr=_coords->getConstPointer();
5987 for(int i=0;i<nbOfCells;i++)
5989 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5990 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5992 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5993 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6000 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6001 * considered to be oriented correctly if an angle between its normal vector and a
6002 * given vector is less than \c PI / \c 2.
6003 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6005 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6007 * \throw If \a this->getMeshDimension() != 2.
6008 * \throw If \a this->getSpaceDimension() != 3.
6010 * \if ENABLE_EXAMPLES
6011 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6012 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6015 * \sa changeOrientationOfCells
6017 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6019 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6020 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6021 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6022 const int *connI(_nodal_connec_index->getConstPointer());
6023 const double *coordsPtr(_coords->getConstPointer());
6024 bool isModified(false);
6025 for(int i=0;i<nbOfCells;i++)
6027 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6028 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6030 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6031 bool isQuadratic(cm.isQuadratic());
6032 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6035 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6040 _nodal_connec->declareAsNew();
6045 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6047 * \sa orientCorrectly2DCells
6049 void MEDCouplingUMesh::changeOrientationOfCells()
6051 int mdim(getMeshDimension());
6052 if(mdim!=2 && mdim!=1)
6053 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6054 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6055 const int *connI(_nodal_connec_index->getConstPointer());
6058 for(int i=0;i<nbOfCells;i++)
6060 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6061 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6062 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6067 for(int i=0;i<nbOfCells;i++)
6069 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6070 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6071 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6077 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6078 * oriented facets. The normal vector of the facet should point out of the cell.
6079 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6080 * is not cleared before filling in.
6081 * \throw If \a this->getMeshDimension() != 3.
6082 * \throw If \a this->getSpaceDimension() != 3.
6083 * \throw If the coordinates array is not set.
6084 * \throw If the nodal connectivity of cells is not defined.
6086 * \if ENABLE_EXAMPLES
6087 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6088 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6091 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6093 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6094 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6095 int nbOfCells=getNumberOfCells();
6096 const int *conn=_nodal_connec->getConstPointer();
6097 const int *connI=_nodal_connec_index->getConstPointer();
6098 const double *coordsPtr=_coords->getConstPointer();
6099 for(int i=0;i<nbOfCells;i++)
6101 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6102 if(type==INTERP_KERNEL::NORM_POLYHED)
6104 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6111 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6113 * \throw If \a this->getMeshDimension() != 3.
6114 * \throw If \a this->getSpaceDimension() != 3.
6115 * \throw If the coordinates array is not set.
6116 * \throw If the nodal connectivity of cells is not defined.
6117 * \throw If the reparation fails.
6119 * \if ENABLE_EXAMPLES
6120 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6121 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6123 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6125 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6127 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6128 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6129 int nbOfCells=getNumberOfCells();
6130 int *conn=_nodal_connec->getPointer();
6131 const int *connI=_nodal_connec_index->getConstPointer();
6132 const double *coordsPtr=_coords->getConstPointer();
6133 for(int i=0;i<nbOfCells;i++)
6135 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6136 if(type==INTERP_KERNEL::NORM_POLYHED)
6140 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6141 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6143 catch(INTERP_KERNEL::Exception& e)
6145 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6146 throw INTERP_KERNEL::Exception(oss.str().c_str());
6154 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6155 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6156 * according to which the first facet of the cell should be oriented to have the normal vector
6157 * pointing out of cell.
6158 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6159 * cells. The caller is to delete this array using decrRef() as it is no more
6161 * \throw If \a this->getMeshDimension() != 3.
6162 * \throw If \a this->getSpaceDimension() != 3.
6163 * \throw If the coordinates array is not set.
6164 * \throw If the nodal connectivity of cells is not defined.
6166 * \if ENABLE_EXAMPLES
6167 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6168 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6170 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6172 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6174 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6175 if(getMeshDimension()!=3)
6176 throw INTERP_KERNEL::Exception(msg);
6177 int spaceDim=getSpaceDimension();
6179 throw INTERP_KERNEL::Exception(msg);
6181 int nbOfCells=getNumberOfCells();
6182 int *conn=_nodal_connec->getPointer();
6183 const int *connI=_nodal_connec_index->getConstPointer();
6184 const double *coo=getCoords()->getConstPointer();
6185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6186 for(int i=0;i<nbOfCells;i++)
6188 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6189 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6191 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6193 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6194 cells->pushBackSilent(i);
6198 return cells.retn();
6202 * This method is a faster method to correct orientation of all 3D cells in \a this.
6203 * 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.
6204 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6206 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6207 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6209 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6211 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6212 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6213 int nbOfCells=getNumberOfCells();
6214 int *conn=_nodal_connec->getPointer();
6215 const int *connI=_nodal_connec_index->getConstPointer();
6216 const double *coordsPtr=_coords->getConstPointer();
6217 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6218 for(int i=0;i<nbOfCells;i++)
6220 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6223 case INTERP_KERNEL::NORM_TETRA4:
6225 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6227 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6228 ret->pushBackSilent(i);
6232 case INTERP_KERNEL::NORM_PYRA5:
6234 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6236 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6237 ret->pushBackSilent(i);
6241 case INTERP_KERNEL::NORM_PENTA6:
6242 case INTERP_KERNEL::NORM_HEXA8:
6243 case INTERP_KERNEL::NORM_HEXGP12:
6245 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6247 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6248 ret->pushBackSilent(i);
6252 case INTERP_KERNEL::NORM_POLYHED:
6254 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6256 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6257 ret->pushBackSilent(i);
6262 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 !");
6270 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6271 * If it is not the case an exception will be thrown.
6272 * This method is fast because the first cell of \a this is used to compute the plane.
6273 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6274 * \param pos output of size at least 3 used to store a point owned of searched plane.
6276 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6278 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6279 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6280 const int *conn=_nodal_connec->getConstPointer();
6281 const int *connI=_nodal_connec_index->getConstPointer();
6282 const double *coordsPtr=_coords->getConstPointer();
6283 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6284 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6288 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6289 * cells. Currently cells of the following types are treated:
6290 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6291 * For a cell of other type an exception is thrown.
6292 * Space dimension of a 2D mesh can be either 2 or 3.
6293 * The Edge Ratio of a cell \f$t\f$ is:
6294 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6295 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6296 * the smallest edge lengths of \f$t\f$.
6297 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6298 * cells and one time, lying on \a this mesh. The caller is to delete this
6299 * field using decrRef() as it is no more needed.
6300 * \throw If the coordinates array is not set.
6301 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6302 * \throw If the connectivity data array has more than one component.
6303 * \throw If the connectivity data array has a named component.
6304 * \throw If the connectivity index data array has more than one component.
6305 * \throw If the connectivity index data array has a named component.
6306 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6307 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6308 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6310 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6313 int spaceDim=getSpaceDimension();
6314 int meshDim=getMeshDimension();
6315 if(spaceDim!=2 && spaceDim!=3)
6316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6317 if(meshDim!=2 && meshDim!=3)
6318 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6319 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6321 int nbOfCells=getNumberOfCells();
6322 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6323 arr->alloc(nbOfCells,1);
6324 double *pt=arr->getPointer();
6325 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6326 const int *conn=_nodal_connec->getConstPointer();
6327 const int *connI=_nodal_connec_index->getConstPointer();
6328 const double *coo=_coords->getConstPointer();
6330 for(int i=0;i<nbOfCells;i++,pt++)
6332 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6335 case INTERP_KERNEL::NORM_TRI3:
6337 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6338 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6341 case INTERP_KERNEL::NORM_QUAD4:
6343 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6344 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6347 case INTERP_KERNEL::NORM_TETRA4:
6349 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6350 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6356 conn+=connI[i+1]-connI[i];
6358 ret->setName("EdgeRatio");
6359 ret->synchronizeTimeWithSupport();
6364 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6365 * cells. Currently cells of the following types are treated:
6366 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6367 * For a cell of other type an exception is thrown.
6368 * Space dimension of a 2D mesh can be either 2 or 3.
6369 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6370 * cells and one time, lying on \a this mesh. The caller is to delete this
6371 * field using decrRef() as it is no more needed.
6372 * \throw If the coordinates array is not set.
6373 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6374 * \throw If the connectivity data array has more than one component.
6375 * \throw If the connectivity data array has a named component.
6376 * \throw If the connectivity index data array has more than one component.
6377 * \throw If the connectivity index data array has a named component.
6378 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6379 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6380 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6382 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6385 int spaceDim=getSpaceDimension();
6386 int meshDim=getMeshDimension();
6387 if(spaceDim!=2 && spaceDim!=3)
6388 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6389 if(meshDim!=2 && meshDim!=3)
6390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6391 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6393 int nbOfCells=getNumberOfCells();
6394 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6395 arr->alloc(nbOfCells,1);
6396 double *pt=arr->getPointer();
6397 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6398 const int *conn=_nodal_connec->getConstPointer();
6399 const int *connI=_nodal_connec_index->getConstPointer();
6400 const double *coo=_coords->getConstPointer();
6402 for(int i=0;i<nbOfCells;i++,pt++)
6404 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6407 case INTERP_KERNEL::NORM_TRI3:
6409 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6410 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6413 case INTERP_KERNEL::NORM_QUAD4:
6415 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6416 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6419 case INTERP_KERNEL::NORM_TETRA4:
6421 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6422 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6428 conn+=connI[i+1]-connI[i];
6430 ret->setName("AspectRatio");
6431 ret->synchronizeTimeWithSupport();
6436 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6437 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6438 * treated: INTERP_KERNEL::NORM_QUAD4.
6439 * For a cell of other type an exception is thrown.
6440 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6441 * cells and one time, lying on \a this mesh. The caller is to delete this
6442 * field using decrRef() as it is no more needed.
6443 * \throw If the coordinates array is not set.
6444 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6445 * \throw If the connectivity data array has more than one component.
6446 * \throw If the connectivity data array has a named component.
6447 * \throw If the connectivity index data array has more than one component.
6448 * \throw If the connectivity index data array has a named component.
6449 * \throw If \a this->getMeshDimension() != 2.
6450 * \throw If \a this->getSpaceDimension() != 3.
6451 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6453 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6456 int spaceDim=getSpaceDimension();
6457 int meshDim=getMeshDimension();
6459 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6461 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6462 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6464 int nbOfCells=getNumberOfCells();
6465 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6466 arr->alloc(nbOfCells,1);
6467 double *pt=arr->getPointer();
6468 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6469 const int *conn=_nodal_connec->getConstPointer();
6470 const int *connI=_nodal_connec_index->getConstPointer();
6471 const double *coo=_coords->getConstPointer();
6473 for(int i=0;i<nbOfCells;i++,pt++)
6475 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6478 case INTERP_KERNEL::NORM_QUAD4:
6480 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6481 *pt=INTERP_KERNEL::quadWarp(tmp);
6485 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6487 conn+=connI[i+1]-connI[i];
6489 ret->setName("Warp");
6490 ret->synchronizeTimeWithSupport();
6496 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6497 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6498 * treated: INTERP_KERNEL::NORM_QUAD4.
6499 * For a cell of other type an exception is thrown.
6500 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6501 * cells and one time, lying on \a this mesh. The caller is to delete this
6502 * field using decrRef() as it is no more needed.
6503 * \throw If the coordinates array is not set.
6504 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6505 * \throw If the connectivity data array has more than one component.
6506 * \throw If the connectivity data array has a named component.
6507 * \throw If the connectivity index data array has more than one component.
6508 * \throw If the connectivity index data array has a named component.
6509 * \throw If \a this->getMeshDimension() != 2.
6510 * \throw If \a this->getSpaceDimension() != 3.
6511 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6513 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6516 int spaceDim=getSpaceDimension();
6517 int meshDim=getMeshDimension();
6519 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6522 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6524 int nbOfCells=getNumberOfCells();
6525 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6526 arr->alloc(nbOfCells,1);
6527 double *pt=arr->getPointer();
6528 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6529 const int *conn=_nodal_connec->getConstPointer();
6530 const int *connI=_nodal_connec_index->getConstPointer();
6531 const double *coo=_coords->getConstPointer();
6533 for(int i=0;i<nbOfCells;i++,pt++)
6535 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6538 case INTERP_KERNEL::NORM_QUAD4:
6540 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6541 *pt=INTERP_KERNEL::quadSkew(tmp);
6545 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6547 conn+=connI[i+1]-connI[i];
6549 ret->setName("Skew");
6550 ret->synchronizeTimeWithSupport();
6555 * 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.
6557 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6559 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6561 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6564 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6566 std::set<INTERP_KERNEL::NormalizedCellType> types;
6567 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6568 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6569 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6570 arr->alloc(nbCells,1);
6571 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6573 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6574 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6575 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6578 ret->setName("Diameter");
6583 * This method aggregate the bbox of each cell and put it into bbox parameter.
6585 * \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)
6586 * For all other cases this input parameter is ignored.
6587 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6589 * \throw If \a this is not fully set (coordinates and connectivity).
6590 * \throw If a cell in \a this has no valid nodeId.
6591 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6593 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6595 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6596 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.
6597 return getBoundingBoxForBBTreeFast();
6598 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6600 bool presenceOfQuadratic(false);
6601 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6603 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6604 if(cm.isQuadratic())
6605 presenceOfQuadratic=true;
6607 if(!presenceOfQuadratic)
6608 return getBoundingBoxForBBTreeFast();
6609 if(mDim==2 && sDim==2)
6610 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6612 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6614 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) !");
6618 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6619 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6621 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6623 * \throw If \a this is not fully set (coordinates and connectivity).
6624 * \throw If a cell in \a this has no valid nodeId.
6626 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6628 checkFullyDefined();
6629 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6630 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6631 double *bbox(ret->getPointer());
6632 for(int i=0;i<nbOfCells*spaceDim;i++)
6634 bbox[2*i]=std::numeric_limits<double>::max();
6635 bbox[2*i+1]=-std::numeric_limits<double>::max();
6637 const double *coordsPtr(_coords->getConstPointer());
6638 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6639 for(int i=0;i<nbOfCells;i++)
6641 int offset=connI[i]+1;
6642 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6643 for(int j=0;j<nbOfNodesForCell;j++)
6645 int nodeId=conn[offset+j];
6646 if(nodeId>=0 && nodeId<nbOfNodes)
6648 for(int k=0;k<spaceDim;k++)
6650 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6651 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6658 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6659 throw INTERP_KERNEL::Exception(oss.str().c_str());
6666 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6667 * useful for 2D meshes having quadratic cells
6668 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6669 * the two extremities of the arc of circle).
6671 * \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)
6672 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6673 * \throw If \a this is not fully defined.
6674 * \throw If \a this is not a mesh with meshDimension equal to 2.
6675 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6676 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6678 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6680 checkFullyDefined();
6681 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6682 if(spaceDim!=2 || mDim!=2)
6683 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!");
6684 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6685 double *bbox(ret->getPointer());
6686 const double *coords(_coords->getConstPointer());
6687 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6688 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6690 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6691 int sz(connI[1]-connI[0]-1);
6692 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6693 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6694 INTERP_KERNEL::QuadraticPolygon *pol(0);
6695 for(int j=0;j<sz;j++)
6697 int nodeId(conn[*connI+1+j]);
6698 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6700 if(!cm.isQuadratic())
6701 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6703 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6704 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6705 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6711 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6712 * useful for 2D meshes having quadratic cells
6713 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6714 * the two extremities of the arc of circle).
6716 * \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)
6717 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6718 * \throw If \a this is not fully defined.
6719 * \throw If \a this is not a mesh with meshDimension equal to 1.
6720 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6721 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6723 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6725 checkFullyDefined();
6726 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6727 if(spaceDim!=2 || mDim!=1)
6728 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!");
6729 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6730 double *bbox(ret->getPointer());
6731 const double *coords(_coords->getConstPointer());
6732 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6733 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6735 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6736 int sz(connI[1]-connI[0]-1);
6737 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6738 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6739 INTERP_KERNEL::Edge *edge(0);
6740 for(int j=0;j<sz;j++)
6742 int nodeId(conn[*connI+1+j]);
6743 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6745 if(!cm.isQuadratic())
6746 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6748 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6749 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6750 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6757 namespace ParaMEDMEMImpl
6762 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6763 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6772 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6773 bool operator() (const int& pos) { return _conn[pos]==_val; }
6783 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6784 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6785 * \a this is composed in cell types.
6786 * The returned array is of size 3*n where n is the number of different types present in \a this.
6787 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6788 * This parameter is kept only for compatibility with other methode listed above.
6790 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6792 checkConnectivityFullyDefined();
6793 const int *conn=_nodal_connec->getConstPointer();
6794 const int *connI=_nodal_connec_index->getConstPointer();
6795 const int *work=connI;
6796 int nbOfCells=getNumberOfCells();
6797 std::size_t n=getAllGeoTypes().size();
6798 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6799 std::set<INTERP_KERNEL::NormalizedCellType> types;
6800 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6802 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6803 if(types.find(typ)!=types.end())
6805 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6806 oss << " is not contiguous !";
6807 throw INTERP_KERNEL::Exception(oss.str().c_str());
6811 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6812 ret[3*i+1]=(int)std::distance(work,work2);
6819 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6820 * only for types cell, type node is not managed.
6821 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6822 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6823 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6824 * If 2 or more same geometric type is in \a code and exception is thrown too.
6826 * This method firstly checks
6827 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6828 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6829 * an exception is thrown too.
6831 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6832 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6833 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6835 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6839 std::size_t sz=code.size();
6842 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6843 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6845 bool isNoPflUsed=true;
6846 for(std::size_t i=0;i<n;i++)
6847 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6849 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6851 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6852 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6853 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6859 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6861 if(types.size()==_types.size())
6864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6866 int *retPtr=ret->getPointer();
6867 const int *connI=_nodal_connec_index->getConstPointer();
6868 const int *conn=_nodal_connec->getConstPointer();
6869 int nbOfCells=getNumberOfCells();
6872 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6874 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6875 int offset=(int)std::distance(connI,i);
6876 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6877 int nbOfCellsOfCurType=(int)std::distance(i,j);
6878 if(code[3*kk+2]==-1)
6879 for(int k=0;k<nbOfCellsOfCurType;k++)
6883 int idInIdsPerType=code[3*kk+2];
6884 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6886 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6889 zePfl->checkAllocated();
6890 if(zePfl->getNumberOfComponents()==1)
6892 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6894 if(*k>=0 && *k<nbOfCellsOfCurType)
6895 *retPtr=(*k)+offset;
6898 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6899 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6900 throw INTERP_KERNEL::Exception(oss.str().c_str());
6905 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6908 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6912 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6913 oss << " should be in [0," << idsPerType.size() << ") !";
6914 throw INTERP_KERNEL::Exception(oss.str().c_str());
6923 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6924 * 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.
6925 * 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.
6926 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6928 * \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.
6929 * \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,
6930 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6931 * \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.
6932 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6933 * \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
6935 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6938 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6939 if(profile->getNumberOfComponents()!=1)
6940 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6941 checkConnectivityFullyDefined();
6942 const int *conn=_nodal_connec->getConstPointer();
6943 const int *connI=_nodal_connec_index->getConstPointer();
6944 int nbOfCells=getNumberOfCells();
6945 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6946 std::vector<int> typeRangeVals(1);
6947 for(const int *i=connI;i!=connI+nbOfCells;)
6949 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6950 if(std::find(types.begin(),types.end(),curType)!=types.end())
6952 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6954 types.push_back(curType);
6955 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6956 typeRangeVals.push_back((int)std::distance(connI,i));
6959 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6960 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6965 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6966 code.resize(3*nbOfCastsFinal);
6967 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6968 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6969 for(int i=0;i<nbOfCastsFinal;i++)
6971 int castId=castsPresent->getIJ(i,0);
6972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6973 idsInPflPerType2.push_back(tmp3);
6974 code[3*i]=(int)types[castId];
6975 code[3*i+1]=tmp3->getNumberOfTuples();
6976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6977 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6979 tmp4->copyStringInfoFrom(*profile);
6980 idsPerType2.push_back(tmp4);
6981 code[3*i+2]=(int)idsPerType2.size()-1;
6988 std::size_t sz2=idsInPflPerType2.size();
6989 idsInPflPerType.resize(sz2);
6990 for(std::size_t i=0;i<sz2;i++)
6992 DataArrayInt *locDa=idsInPflPerType2[i];
6994 idsInPflPerType[i]=locDa;
6996 std::size_t sz=idsPerType2.size();
6997 idsPerType.resize(sz);
6998 for(std::size_t i=0;i<sz;i++)
7000 DataArrayInt *locDa=idsPerType2[i];
7002 idsPerType[i]=locDa;
7007 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7008 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7009 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7010 * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
7012 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7014 checkFullyDefined();
7015 nM1LevMesh->checkFullyDefined();
7016 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7017 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7018 if(_coords!=nM1LevMesh->getCoords())
7019 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7020 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7021 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7022 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7024 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7025 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7026 tmp->setConnectivity(tmp0,tmp1);
7027 tmp->renumberCells(ret0->getConstPointer(),false);
7028 revDesc=tmp->getNodalConnectivity();
7029 revDescIndx=tmp->getNodalConnectivityIndex();
7030 DataArrayInt *ret=0;
7031 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7034 ret->getMaxValue(tmp2);
7036 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7037 throw INTERP_KERNEL::Exception(oss.str().c_str());
7042 revDescIndx->incrRef();
7045 meshnM1Old2New=ret0;
7050 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7051 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7052 * in "Old to New" mode.
7053 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7054 * this array using decrRef() as it is no more needed.
7055 * \throw If the nodal connectivity of cells is not defined.
7057 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7059 checkConnectivityFullyDefined();
7060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7061 renumberCells(ret->getConstPointer(),false);
7066 * This methods checks that cells are sorted by their types.
7067 * This method makes asumption (no check) that connectivity is correctly set before calling.
7069 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7071 checkFullyDefined();
7072 const int *conn=_nodal_connec->getConstPointer();
7073 const int *connI=_nodal_connec_index->getConstPointer();
7074 int nbOfCells=getNumberOfCells();
7075 std::set<INTERP_KERNEL::NormalizedCellType> types;
7076 for(const int *i=connI;i!=connI+nbOfCells;)
7078 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7079 if(types.find(curType)!=types.end())
7081 types.insert(curType);
7082 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7088 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7089 * The geometric type order is specified by MED file.
7091 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7093 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7095 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7099 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7100 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7101 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7102 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7104 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7106 checkFullyDefined();
7107 const int *conn=_nodal_connec->getConstPointer();
7108 const int *connI=_nodal_connec_index->getConstPointer();
7109 int nbOfCells=getNumberOfCells();
7113 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7114 for(const int *i=connI;i!=connI+nbOfCells;)
7116 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7117 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7118 if(isTypeExists!=orderEnd)
7120 int pos=(int)std::distance(orderBg,isTypeExists);
7124 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7128 if(sg.find(curType)==sg.end())
7130 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7141 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7142 * 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
7143 * 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'.
7145 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7147 checkConnectivityFullyDefined();
7148 int nbOfCells=getNumberOfCells();
7149 const int *conn=_nodal_connec->getConstPointer();
7150 const int *connI=_nodal_connec_index->getConstPointer();
7151 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7152 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7153 tmpa->alloc(nbOfCells,1);
7154 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7155 tmpb->fillWithZero();
7156 int *tmp=tmpa->getPointer();
7157 int *tmp2=tmpb->getPointer();
7158 for(const int *i=connI;i!=connI+nbOfCells;i++)
7160 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7163 int pos=(int)std::distance(orderBg,where);
7165 tmp[std::distance(connI,i)]=pos;
7169 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7170 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7171 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7172 throw INTERP_KERNEL::Exception(oss.str().c_str());
7175 nbPerType=tmpb.retn();
7180 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7182 * \return a new object containing the old to new correspondance.
7184 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7186 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7188 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7192 * 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.
7193 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7194 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7195 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7197 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7199 DataArrayInt *nbPerType=0;
7200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7201 nbPerType->decrRef();
7202 return tmpa->buildPermArrPerLevel();
7206 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7207 * The number of cells remains unchanged after the call of this method.
7208 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7209 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7211 * \return the array giving the correspondance old to new.
7213 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7215 checkFullyDefined();
7217 const int *conn=_nodal_connec->getConstPointer();
7218 const int *connI=_nodal_connec_index->getConstPointer();
7219 int nbOfCells=getNumberOfCells();
7220 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7221 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7222 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7224 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7225 types.push_back(curType);
7226 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7228 DataArrayInt *ret=DataArrayInt::New();
7229 ret->alloc(nbOfCells,1);
7230 int *retPtr=ret->getPointer();
7231 std::fill(retPtr,retPtr+nbOfCells,-1);
7233 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7235 for(const int *i=connI;i!=connI+nbOfCells;i++)
7236 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7237 retPtr[std::distance(connI,i)]=newCellId++;
7239 renumberCells(retPtr,false);
7244 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7245 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7246 * This method makes asumption that connectivity is correctly set before calling.
7248 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7250 checkConnectivityFullyDefined();
7251 const int *conn=_nodal_connec->getConstPointer();
7252 const int *connI=_nodal_connec_index->getConstPointer();
7253 int nbOfCells=getNumberOfCells();
7254 std::vector<MEDCouplingUMesh *> ret;
7255 for(const int *i=connI;i!=connI+nbOfCells;)
7257 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7258 int beginCellId=(int)std::distance(connI,i);
7259 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7260 int endCellId=(int)std::distance(connI,i);
7261 int sz=endCellId-beginCellId;
7262 int *cells=new int[sz];
7263 for(int j=0;j<sz;j++)
7264 cells[j]=beginCellId+j;
7265 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7273 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7274 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7275 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7277 * \return a newly allocated instance, that the caller must manage.
7278 * \throw If \a this contains more than one geometric type.
7279 * \throw If the nodal connectivity of \a this is not fully defined.
7280 * \throw If the internal data is not coherent.
7282 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7284 checkConnectivityFullyDefined();
7285 if(_types.size()!=1)
7286 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7287 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7288 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7289 ret->setCoords(getCoords());
7290 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7294 retC->setNodalConnectivity(c);
7298 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7300 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7301 DataArrayInt *c=0,*ci=0;
7302 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7303 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7304 retD->setNodalConnectivity(cs,cis);
7309 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7311 checkConnectivityFullyDefined();
7312 if(_types.size()!=1)
7313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7314 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7315 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7318 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7319 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7320 throw INTERP_KERNEL::Exception(oss.str().c_str());
7322 int nbCells=getNumberOfCells();
7324 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7326 int *outPtr=connOut->getPointer();
7327 const int *conn=_nodal_connec->begin();
7328 const int *connI=_nodal_connec_index->begin();
7330 for(int i=0;i<nbCells;i++,connI++)
7332 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7333 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7336 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 << ") !";
7337 throw INTERP_KERNEL::Exception(oss.str().c_str());
7340 return connOut.retn();
7343 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7345 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7346 checkConnectivityFullyDefined();
7347 if(_types.size()!=1)
7348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7349 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7351 throw INTERP_KERNEL::Exception(msg0);
7352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7353 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7354 int *cp(c->getPointer()),*cip(ci->getPointer());
7355 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7357 for(int i=0;i<nbCells;i++,cip++,incip++)
7359 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7360 int delta(stop-strt);
7363 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7364 cp=std::copy(incp+strt,incp+stop,cp);
7366 throw INTERP_KERNEL::Exception(msg0);
7369 throw INTERP_KERNEL::Exception(msg0);
7370 cip[1]=cip[0]+delta;
7372 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7376 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7377 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7378 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7379 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7380 * are not used here to avoid the build of big permutation array.
7382 * \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
7383 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7384 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7385 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7386 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7387 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7388 * \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
7389 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7391 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7392 DataArrayInt *&szOfCellGrpOfSameType,
7393 DataArrayInt *&idInMsOfCellGrpOfSameType)
7395 std::vector<const MEDCouplingUMesh *> ms2;
7396 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7399 (*it)->checkConnectivityFullyDefined();
7403 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7404 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7405 int meshDim=ms2[0]->getMeshDimension();
7406 std::vector<const MEDCouplingUMesh *> m1ssm;
7407 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7409 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7410 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7413 ret1->alloc(0,1); ret2->alloc(0,1);
7414 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7416 if(meshDim!=(*it)->getMeshDimension())
7417 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7418 if(refCoo!=(*it)->getCoords())
7419 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7420 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7421 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7422 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7423 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7425 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7426 m1ssmSingleAuto.push_back(singleCell);
7427 m1ssmSingle.push_back(singleCell);
7428 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7431 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7433 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7434 for(std::size_t i=0;i<m1ssm.size();i++)
7435 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7436 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7437 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7438 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7443 * This method returns a newly created DataArrayInt instance.
7444 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7446 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7448 checkFullyDefined();
7449 const int *conn=_nodal_connec->getConstPointer();
7450 const int *connIndex=_nodal_connec_index->getConstPointer();
7451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7452 for(const int *w=begin;w!=end;w++)
7453 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7454 ret->pushBackSilent(*w);
7459 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7460 * are in [0:getNumberOfCells())
7462 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7464 checkFullyDefined();
7465 const int *conn=_nodal_connec->getConstPointer();
7466 const int *connI=_nodal_connec_index->getConstPointer();
7467 int nbOfCells=getNumberOfCells();
7468 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7469 int *tmp=new int[nbOfCells];
7470 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7473 for(const int *i=connI;i!=connI+nbOfCells;i++)
7474 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7475 tmp[std::distance(connI,i)]=j++;
7477 DataArrayInt *ret=DataArrayInt::New();
7478 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7479 ret->copyStringInfoFrom(*da);
7480 int *retPtr=ret->getPointer();
7481 const int *daPtr=da->getConstPointer();
7482 int nbOfElems=da->getNbOfElems();
7483 for(int k=0;k<nbOfElems;k++)
7484 retPtr[k]=tmp[daPtr[k]];
7490 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7491 * This method \b works \b for mesh sorted by type.
7492 * cells whose ids is in 'idsPerGeoType' array.
7493 * This method conserves coords and name of mesh.
7495 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7497 std::vector<int> code=getDistributionOfTypes();
7498 std::size_t nOfTypesInThis=code.size()/3;
7499 int sz=0,szOfType=0;
7500 for(std::size_t i=0;i<nOfTypesInThis;i++)
7505 szOfType=code[3*i+1];
7507 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7508 if(*work<0 || *work>=szOfType)
7510 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7511 oss << ". It should be in [0," << szOfType << ") !";
7512 throw INTERP_KERNEL::Exception(oss.str().c_str());
7514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7515 int *idsPtr=idsTokeep->getPointer();
7517 for(std::size_t i=0;i<nOfTypesInThis;i++)
7520 for(int j=0;j<code[3*i+1];j++)
7523 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7524 offset+=code[3*i+1];
7526 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7527 ret->copyTinyInfoFrom(this);
7532 * This method returns a vector of size 'this->getNumberOfCells()'.
7533 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7535 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7537 int ncell=getNumberOfCells();
7538 std::vector<bool> ret(ncell);
7539 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7540 const int *c=getNodalConnectivity()->getConstPointer();
7541 for(int i=0;i<ncell;i++)
7543 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7544 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7545 ret[i]=cm.isQuadratic();
7551 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7553 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7555 if(other->getType()!=UNSTRUCTURED)
7556 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7557 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7558 return MergeUMeshes(this,otherC);
7562 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7563 * computed by averaging coordinates of cell nodes, so this method is not a right
7564 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7565 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7566 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7567 * components. The caller is to delete this array using decrRef() as it is
7569 * \throw If the coordinates array is not set.
7570 * \throw If the nodal connectivity of cells is not defined.
7571 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7573 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7575 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7576 int spaceDim=getSpaceDimension();
7577 int nbOfCells=getNumberOfCells();
7578 ret->alloc(nbOfCells,spaceDim);
7579 ret->copyStringInfoFrom(*getCoords());
7580 double *ptToFill=ret->getPointer();
7581 const int *nodal=_nodal_connec->getConstPointer();
7582 const int *nodalI=_nodal_connec_index->getConstPointer();
7583 const double *coor=_coords->getConstPointer();
7584 for(int i=0;i<nbOfCells;i++)
7586 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7587 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7594 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7595 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7597 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7598 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7600 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7601 * \throw If \a this is not fully defined (coordinates and connectivity)
7602 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7604 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7606 checkFullyDefined();
7607 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7608 int spaceDim=getSpaceDimension();
7609 int nbOfCells=getNumberOfCells();
7610 int nbOfNodes=getNumberOfNodes();
7611 ret->alloc(nbOfCells,spaceDim);
7612 double *ptToFill=ret->getPointer();
7613 const int *nodal=_nodal_connec->getConstPointer();
7614 const int *nodalI=_nodal_connec_index->getConstPointer();
7615 const double *coor=_coords->getConstPointer();
7616 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7618 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7619 std::fill(ptToFill,ptToFill+spaceDim,0.);
7620 if(type!=INTERP_KERNEL::NORM_POLYHED)
7622 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7624 if(*conn>=0 && *conn<nbOfNodes)
7625 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7628 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7629 throw INTERP_KERNEL::Exception(oss.str().c_str());
7632 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7633 if(nbOfNodesInCell>0)
7634 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7637 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7638 throw INTERP_KERNEL::Exception(oss.str().c_str());
7643 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7645 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7647 if(*it>=0 && *it<nbOfNodes)
7648 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7651 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7652 throw INTERP_KERNEL::Exception(oss.str().c_str());
7656 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7659 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7660 throw INTERP_KERNEL::Exception(oss.str().c_str());
7668 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7669 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7670 * are specified via an array of cell ids.
7671 * \warning Validity of the specified cell ids is not checked!
7672 * Valid range is [ 0, \a this->getNumberOfCells() ).
7673 * \param [in] begin - an array of cell ids of interest.
7674 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7675 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7676 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7677 * caller is to delete this array using decrRef() as it is no more needed.
7678 * \throw If the coordinates array is not set.
7679 * \throw If the nodal connectivity of cells is not defined.
7681 * \if ENABLE_EXAMPLES
7682 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7683 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7686 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7688 DataArrayDouble *ret=DataArrayDouble::New();
7689 int spaceDim=getSpaceDimension();
7690 int nbOfTuple=(int)std::distance(begin,end);
7691 ret->alloc(nbOfTuple,spaceDim);
7692 double *ptToFill=ret->getPointer();
7693 double *tmp=new double[spaceDim];
7694 const int *nodal=_nodal_connec->getConstPointer();
7695 const int *nodalI=_nodal_connec_index->getConstPointer();
7696 const double *coor=_coords->getConstPointer();
7697 for(const int *w=begin;w!=end;w++)
7699 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7700 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7708 * 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".
7709 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7710 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7711 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7712 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7714 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7715 * \throw If spaceDim!=3 or meshDim!=2.
7716 * \throw If connectivity of \a this is invalid.
7717 * \throw If connectivity of a cell in \a this points to an invalid node.
7719 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7721 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7722 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7723 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7724 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7725 ret->alloc(nbOfCells,4);
7726 double *retPtr(ret->getPointer());
7727 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7728 const double *coor(_coords->begin());
7729 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7731 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7732 if(nodalI[1]-nodalI[0]>=3)
7734 for(int j=0;j<3;j++)
7736 int nodeId(nodal[nodalI[0]+1+j]);
7737 if(nodeId>=0 && nodeId<nbOfNodes)
7738 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7741 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7742 throw INTERP_KERNEL::Exception(oss.str().c_str());
7748 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7749 throw INTERP_KERNEL::Exception(oss.str().c_str());
7751 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7752 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7758 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7761 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7764 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7765 da->checkAllocated();
7766 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7768 int nbOfTuples=da->getNumberOfTuples();
7769 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7770 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7771 c->alloc(2*nbOfTuples,1);
7772 cI->alloc(nbOfTuples+1,1);
7773 int *cp=c->getPointer();
7774 int *cip=cI->getPointer();
7776 for(int i=0;i<nbOfTuples;i++)
7778 *cp++=INTERP_KERNEL::NORM_POINT1;
7782 ret->setConnectivity(c,cI,true);
7786 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7787 * Cells and nodes of
7788 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7789 * \param [in] mesh1 - the first mesh.
7790 * \param [in] mesh2 - the second mesh.
7791 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7792 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7793 * is no more needed.
7794 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7795 * \throw If the coordinates array is not set in none of the meshes.
7796 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7797 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7799 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7801 std::vector<const MEDCouplingUMesh *> tmp(2);
7802 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7803 return MergeUMeshes(tmp);
7807 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7808 * Cells and nodes of
7809 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7810 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7811 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7812 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7813 * is no more needed.
7814 * \throw If \a a.size() == 0.
7815 * \throw If \a a[ *i* ] == NULL.
7816 * \throw If the coordinates array is not set in none of the meshes.
7817 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7818 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7820 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7822 std::size_t sz=a.size();
7824 return MergeUMeshesLL(a);
7825 for(std::size_t ii=0;ii<sz;ii++)
7828 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7829 throw INTERP_KERNEL::Exception(oss.str().c_str());
7831 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7832 std::vector< const MEDCouplingUMesh * > aa(sz);
7834 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7836 const MEDCouplingUMesh *cur=a[i];
7837 const DataArrayDouble *coo=cur->getCoords();
7839 spaceDim=coo->getNumberOfComponents();
7842 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7843 for(std::size_t i=0;i<sz;i++)
7845 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7848 return MergeUMeshesLL(aa);
7853 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7857 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7858 int meshDim=(*it)->getMeshDimension();
7859 int nbOfCells=(*it)->getNumberOfCells();
7860 int meshLgth=(*it++)->getMeshLength();
7861 for(;it!=a.end();it++)
7863 if(meshDim!=(*it)->getMeshDimension())
7864 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7865 nbOfCells+=(*it)->getNumberOfCells();
7866 meshLgth+=(*it)->getMeshLength();
7868 std::vector<const MEDCouplingPointSet *> aps(a.size());
7869 std::copy(a.begin(),a.end(),aps.begin());
7870 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7871 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7872 ret->setCoords(pts);
7873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7874 c->alloc(meshLgth,1);
7875 int *cPtr=c->getPointer();
7876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7877 cI->alloc(nbOfCells+1,1);
7878 int *cIPtr=cI->getPointer();
7882 for(it=a.begin();it!=a.end();it++)
7884 int curNbOfCell=(*it)->getNumberOfCells();
7885 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7886 const int *curC=(*it)->_nodal_connec->getConstPointer();
7887 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7888 for(int j=0;j<curNbOfCell;j++)
7890 const int *src=curC+curCI[j];
7892 for(;src!=curC+curCI[j+1];src++,cPtr++)
7900 offset+=curCI[curNbOfCell];
7901 offset2+=(*it)->getNumberOfNodes();
7904 ret->setConnectivity(c,cI,true);
7911 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7912 * dimension and sharing the node coordinates array.
7913 * All cells of the first mesh precede all cells of the second mesh
7914 * within the result mesh.
7915 * \param [in] mesh1 - the first mesh.
7916 * \param [in] mesh2 - the second mesh.
7917 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7918 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7919 * is no more needed.
7920 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7921 * \throw If the meshes do not share the node coordinates array.
7922 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7923 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7925 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7927 std::vector<const MEDCouplingUMesh *> tmp(2);
7928 tmp[0]=mesh1; tmp[1]=mesh2;
7929 return MergeUMeshesOnSameCoords(tmp);
7933 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7934 * dimension and sharing the node coordinates array.
7935 * All cells of the *i*-th mesh precede all cells of the
7936 * (*i*+1)-th mesh within the result mesh.
7937 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7938 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7939 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7940 * is no more needed.
7941 * \throw If \a a.size() == 0.
7942 * \throw If \a a[ *i* ] == NULL.
7943 * \throw If the meshes do not share the node coordinates array.
7944 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7945 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7947 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7950 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7951 for(std::size_t ii=0;ii<meshes.size();ii++)
7954 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7955 throw INTERP_KERNEL::Exception(oss.str().c_str());
7957 const DataArrayDouble *coords=meshes.front()->getCoords();
7958 int meshDim=meshes.front()->getMeshDimension();
7959 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7961 int meshIndexLgth=0;
7962 for(;iter!=meshes.end();iter++)
7964 if(coords!=(*iter)->getCoords())
7965 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7966 if(meshDim!=(*iter)->getMeshDimension())
7967 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7968 meshLgth+=(*iter)->getMeshLength();
7969 meshIndexLgth+=(*iter)->getNumberOfCells();
7971 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7972 nodal->alloc(meshLgth,1);
7973 int *nodalPtr=nodal->getPointer();
7974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7975 nodalIndex->alloc(meshIndexLgth+1,1);
7976 int *nodalIndexPtr=nodalIndex->getPointer();
7978 for(iter=meshes.begin();iter!=meshes.end();iter++)
7980 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7981 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7982 int nbOfCells=(*iter)->getNumberOfCells();
7983 int meshLgth2=(*iter)->getMeshLength();
7984 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7985 if(iter!=meshes.begin())
7986 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7988 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7991 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7992 ret->setName("merge");
7993 ret->setMeshDimension(meshDim);
7994 ret->setConnectivity(nodal,nodalIndex,true);
7995 ret->setCoords(coords);
8000 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8001 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8002 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8003 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8004 * New" mode are returned for each input mesh.
8005 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8006 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8007 * valid values [0,1,2], see zipConnectivityTraducer().
8008 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8009 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8010 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8012 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8013 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8014 * is no more needed.
8015 * \throw If \a meshes.size() == 0.
8016 * \throw If \a meshes[ *i* ] == NULL.
8017 * \throw If the meshes do not share the node coordinates array.
8018 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8019 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8020 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8021 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8023 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8025 //All checks are delegated to MergeUMeshesOnSameCoords
8026 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8027 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8028 corr.resize(meshes.size());
8029 std::size_t nbOfMeshes=meshes.size();
8031 const int *o2nPtr=o2n->getConstPointer();
8032 for(std::size_t i=0;i<nbOfMeshes;i++)
8034 DataArrayInt *tmp=DataArrayInt::New();
8035 int curNbOfCells=meshes[i]->getNumberOfCells();
8036 tmp->alloc(curNbOfCells,1);
8037 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8038 offset+=curNbOfCells;
8039 tmp->setName(meshes[i]->getName());
8046 * Makes all given meshes share the nodal connectivity array. The common connectivity
8047 * array is created by concatenating the connectivity arrays of all given meshes. All
8048 * the given meshes must be of the same space dimension but dimension of cells **can
8049 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8050 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8051 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8052 * \param [in,out] meshes - a vector of meshes to update.
8053 * \throw If any of \a meshes is NULL.
8054 * \throw If the coordinates array is not set in any of \a meshes.
8055 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8056 * \throw If \a meshes are of different space dimension.
8058 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8060 std::size_t sz=meshes.size();
8063 std::vector< const DataArrayDouble * > coords(meshes.size());
8064 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8065 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8069 (*it)->checkConnectivityFullyDefined();
8070 const DataArrayDouble *coo=(*it)->getCoords();
8075 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8076 oss << " has no coordinate array defined !";
8077 throw INTERP_KERNEL::Exception(oss.str().c_str());
8082 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8083 oss << " is null !";
8084 throw INTERP_KERNEL::Exception(oss.str().c_str());
8087 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8088 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8089 int offset=(*it)->getNumberOfNodes();
8090 (*it++)->setCoords(res);
8091 for(;it!=meshes.end();it++)
8093 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8094 (*it)->setCoords(res);
8095 (*it)->shiftNodeNumbersInConn(offset);
8096 offset+=oldNumberOfNodes;
8101 * Merges nodes coincident with a given precision within all given meshes that share
8102 * the nodal connectivity array. The given meshes **can be of different** mesh
8103 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8104 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8105 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8106 * \param [in,out] meshes - a vector of meshes to update.
8107 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8108 * \throw If any of \a meshes is NULL.
8109 * \throw If the \a meshes do not share the same node coordinates array.
8110 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8112 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8116 std::set<const DataArrayDouble *> s;
8117 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8120 s.insert((*it)->getCoords());
8123 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 !";
8124 throw INTERP_KERNEL::Exception(oss.str().c_str());
8129 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 !";
8130 throw INTERP_KERNEL::Exception(oss.str().c_str());
8132 const DataArrayDouble *coo=*(s.begin());
8136 DataArrayInt *comm,*commI;
8137 coo->findCommonTuples(eps,-1,comm,commI);
8138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8139 int oldNbOfNodes=coo->getNumberOfTuples();
8141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8142 if(oldNbOfNodes==newNbOfNodes)
8144 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8145 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8147 (*it)->renumberNodesInConn(o2n->getConstPointer());
8148 (*it)->setCoords(newCoords);
8153 * 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.
8154 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8155 * \param isQuad specifies the policy of connectivity.
8156 * @ret in/out parameter in which the result will be append
8158 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8160 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8161 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8162 ret.push_back(cm.getExtrudedType());
8163 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8166 case INTERP_KERNEL::NORM_POINT1:
8168 ret.push_back(connBg[1]);
8169 ret.push_back(connBg[1]+nbOfNodesPerLev);
8172 case INTERP_KERNEL::NORM_SEG2:
8174 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8175 ret.insert(ret.end(),conn,conn+4);
8178 case INTERP_KERNEL::NORM_SEG3:
8180 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8181 ret.insert(ret.end(),conn,conn+8);
8184 case INTERP_KERNEL::NORM_QUAD4:
8186 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8187 ret.insert(ret.end(),conn,conn+8);
8190 case INTERP_KERNEL::NORM_TRI3:
8192 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8193 ret.insert(ret.end(),conn,conn+6);
8196 case INTERP_KERNEL::NORM_TRI6:
8198 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,
8199 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8200 ret.insert(ret.end(),conn,conn+15);
8203 case INTERP_KERNEL::NORM_QUAD8:
8206 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8207 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8208 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8210 ret.insert(ret.end(),conn,conn+20);
8213 case INTERP_KERNEL::NORM_POLYGON:
8215 std::back_insert_iterator< std::vector<int> > ii(ret);
8216 std::copy(connBg+1,connEnd,ii);
8218 std::reverse_iterator<const int *> rConnBg(connEnd);
8219 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8220 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8221 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8222 for(std::size_t i=0;i<nbOfRadFaces;i++)
8225 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8226 std::copy(conn,conn+4,ii);
8231 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8236 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8238 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8241 double v[3]={0.,0.,0.};
8242 std::size_t sz=std::distance(begin,end);
8247 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];
8248 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8249 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8251 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8253 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8254 // SEG3 forming a circle):
8255 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8257 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8258 for(std::size_t j=0;j<sz;j++)
8260 if (j%2) // current point i is quadratic, next point i+1 is standard
8263 ip1 = (j+1)%sz; // ip1 = "i+1"
8265 else // current point i is standard, next point i+1 is quadratic
8270 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8271 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8272 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8274 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8280 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8282 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8284 std::vector<std::pair<int,int> > edges;
8285 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8286 const int *bgFace=begin;
8287 for(std::size_t i=0;i<nbOfFaces;i++)
8289 const int *endFace=std::find(bgFace+1,end,-1);
8290 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8291 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8293 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8294 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8296 edges.push_back(p1);
8300 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8304 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8306 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8308 double vec0[3],vec1[3];
8309 std::size_t sz=std::distance(begin,end);
8311 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8312 int nbOfNodes=(int)sz/2;
8313 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8314 const double *pt0=coords+3*begin[0];
8315 const double *pt1=coords+3*begin[nbOfNodes];
8316 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8317 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8320 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8322 std::size_t sz=std::distance(begin,end);
8323 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8324 std::size_t nbOfNodes(sz/2);
8325 std::copy(begin,end,(int *)tmp);
8326 for(std::size_t j=1;j<nbOfNodes;j++)
8328 begin[j]=tmp[nbOfNodes-j];
8329 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8333 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8335 std::size_t sz=std::distance(begin,end);
8337 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8338 double vec0[3],vec1[3];
8339 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8340 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];
8341 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;
8344 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8346 std::size_t sz=std::distance(begin,end);
8348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8350 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8351 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8352 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8356 * 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 )
8357 * 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
8360 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8361 * \param [in] coords the coordinates with nb of components exactly equal to 3
8362 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8363 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8364 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8366 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8368 int nbFaces=std::count(begin+1,end,-1)+1;
8369 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8370 double *vPtr=v->getPointer();
8371 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8372 double *pPtr=p->getPointer();
8373 const int *stFaceConn=begin+1;
8374 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8376 const int *endFaceConn=std::find(stFaceConn,end,-1);
8377 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8378 stFaceConn=endFaceConn+1;
8380 pPtr=p->getPointer(); vPtr=v->getPointer();
8381 DataArrayInt *comm1=0,*commI1=0;
8382 v->findCommonTuples(eps,-1,comm1,commI1);
8383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8384 const int *comm1Ptr=comm1->getConstPointer();
8385 const int *commI1Ptr=commI1->getConstPointer();
8386 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8387 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8389 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8390 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8391 mm->finishInsertingCells();
8393 for(int i=0;i<nbOfGrps1;i++)
8395 int vecId=comm1Ptr[commI1Ptr[i]];
8396 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8397 DataArrayInt *comm2=0,*commI2=0;
8398 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8400 const int *comm2Ptr=comm2->getConstPointer();
8401 const int *commI2Ptr=commI2->getConstPointer();
8402 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8403 for(int j=0;j<nbOfGrps2;j++)
8405 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8407 res->insertAtTheEnd(begin,end);
8408 res->pushBackSilent(-1);
8412 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8414 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8415 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8416 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8417 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8420 const int *idsNodePtr=idsNode->getConstPointer();
8421 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];
8422 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8423 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8424 if(std::abs(norm)>eps)
8426 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8427 mm3->rotate(center,vec,angle);
8429 mm3->changeSpaceDimension(2);
8430 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8431 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8432 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8433 int nbOfCells=mm4->getNumberOfCells();
8434 for(int k=0;k<nbOfCells;k++)
8437 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8438 res->pushBackSilent(idsNodePtr[*work]);
8439 res->pushBackSilent(-1);
8444 res->popBackSilent();
8448 * 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
8449 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8451 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8452 * \param [in] coords coordinates expected to have 3 components.
8453 * \param [in] begin start of the nodal connectivity of the face.
8454 * \param [in] end end of the nodal connectivity (excluded) of the face.
8455 * \param [out] v the normalized vector of size 3
8456 * \param [out] p the pos of plane
8458 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8460 std::size_t nbPoints=std::distance(begin,end);
8462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8463 double vec[3]={0.,0.,0.};
8465 bool refFound=false;
8466 for(;j<nbPoints-1 && !refFound;j++)
8468 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8469 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8470 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8471 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8475 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8478 for(std::size_t i=j;i<nbPoints-1;i++)
8481 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8482 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8483 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8484 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8487 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8488 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];
8489 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8492 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8493 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8497 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8501 * This method tries to obtain a well oriented polyhedron.
8502 * If the algorithm fails, an exception will be thrown.
8504 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8506 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8507 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8508 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8510 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8511 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8512 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8514 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8517 std::size_t smthChanged=0;
8518 for(std::size_t i=0;i<nbOfFaces;i++)
8520 endFace=std::find(bgFace+1,end,-1);
8521 nbOfEdgesInFace=std::distance(bgFace,endFace);
8525 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8527 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8528 std::pair<int,int> p2(p1.second,p1.first);
8529 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8530 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8531 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8536 std::reverse(bgFace+1,endFace);
8537 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8539 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8540 std::pair<int,int> p2(p1.second,p1.first);
8541 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8542 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8543 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8544 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8545 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8546 if(it!=edgesOK.end())
8549 edgesFinished.push_back(p1);
8552 edgesOK.push_back(p1);
8559 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8561 if(!edgesOK.empty())
8562 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8563 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8564 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8566 for(std::size_t i=0;i<nbOfFaces;i++)
8568 endFace=std::find(bgFace+1,end,-1);
8569 std::reverse(bgFace+1,endFace);
8575 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8577 int nbOfNodesExpected(skin->getNumberOfNodes());
8578 const int *n2oPtr(n2o->getConstPointer());
8579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8580 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8581 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8582 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8583 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8584 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8585 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8586 if(nbOfNodesExpected<1)
8588 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8589 *work++=n2oPtr[prevNode];
8590 for(int i=1;i<nbOfNodesExpected;i++)
8592 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8594 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8595 conn.erase(prevNode);
8598 int curNode(*(conn.begin()));
8599 *work++=n2oPtr[curNode];
8600 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8601 shar.erase(prevCell);
8604 prevCell=*(shar.begin());
8608 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8611 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8614 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8619 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8621 int nbOfNodesExpected(skin->getNumberOfNodes());
8622 int nbOfTurn(nbOfNodesExpected/2);
8623 const int *n2oPtr(n2o->getConstPointer());
8624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8625 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8626 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8627 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8628 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8630 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8631 if(nbOfNodesExpected<1)
8633 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8634 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8635 for(int i=1;i<nbOfTurn;i++)
8637 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8639 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8640 conn.erase(prevNode);
8643 int curNode(*(conn.begin()));
8644 *work=n2oPtr[curNode];
8645 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8646 shar.erase(prevCell);
8649 int curCell(*(shar.begin()));
8650 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8659 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8662 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8668 * This method makes the assumption spacedimension == meshdimension == 2.
8669 * This method works only for linear cells.
8671 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8673 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8675 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8677 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8678 int oldNbOfNodes(skin->getNumberOfNodes());
8679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8680 int nbOfNodesExpected(skin->getNumberOfNodes());
8681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8682 int nbCells(skin->getNumberOfCells());
8683 if(nbCells==nbOfNodesExpected)
8684 return buildUnionOf2DMeshLinear(skin,n2o);
8685 else if(2*nbCells==nbOfNodesExpected)
8686 return buildUnionOf2DMeshQuadratic(skin,n2o);
8688 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8692 * This method makes the assumption spacedimension == meshdimension == 3.
8693 * This method works only for linear cells.
8695 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8697 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8699 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8701 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8702 const int *conn=m->getNodalConnectivity()->getConstPointer();
8703 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8704 int nbOfCells=m->getNumberOfCells();
8705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8706 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8709 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8710 for(int i=1;i<nbOfCells;i++)
8713 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8719 * \brief Creates a graph of cell neighbors
8720 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8721 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8723 * - index: 0 3 5 6 6
8724 * - value: 1 2 3 2 3 3
8725 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8726 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8728 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8730 checkConnectivityFullyDefined();
8732 int meshDim = this->getMeshDimension();
8733 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8734 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8735 this->getReverseNodalConnectivity(revConn,indexr);
8736 const int* indexr_ptr=indexr->getConstPointer();
8737 const int* revConn_ptr=revConn->getConstPointer();
8739 const ParaMEDMEM::DataArrayInt* index;
8740 const ParaMEDMEM::DataArrayInt* conn;
8741 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8742 index=this->getNodalConnectivityIndex();
8743 int nbCells=this->getNumberOfCells();
8744 const int* index_ptr=index->getConstPointer();
8745 const int* conn_ptr=conn->getConstPointer();
8747 //creating graph arcs (cell to cell relations)
8748 //arcs are stored in terms of (index,value) notation
8751 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8752 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8754 //warning here one node have less than or equal effective number of cell with it
8755 //but cell could have more than effective nodes
8756 //because other equals nodes in other domain (with other global inode)
8757 std::vector <int> cell2cell_index(nbCells+1,0);
8758 std::vector <int> cell2cell;
8759 cell2cell.reserve(3*nbCells);
8761 for (int icell=0; icell<nbCells;icell++)
8763 std::map<int,int > counter;
8764 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8766 int inode=conn_ptr[iconn];
8767 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8769 int icell2=revConn_ptr[iconnr];
8770 std::map<int,int>::iterator iter=counter.find(icell2);
8771 if (iter!=counter.end()) (iter->second)++;
8772 else counter.insert(std::make_pair(icell2,1));
8775 for (std::map<int,int>::const_iterator iter=counter.begin();
8776 iter!=counter.end(); iter++)
8777 if (iter->second >= meshDim)
8779 cell2cell_index[icell+1]++;
8780 cell2cell.push_back(iter->first);
8785 cell2cell_index[0]=0;
8786 for (int icell=0; icell<nbCells;icell++)
8787 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8789 //filling up index and value to create skylinearray structure
8790 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8795 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8796 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8798 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8802 for(int i=0;i<nbOfNodesInCell;i++)
8803 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8804 else if(spaceDim==2)
8806 for(int i=0;i<nbOfNodesInCell;i++)
8808 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8813 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8816 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8818 int nbOfCells=getNumberOfCells();
8820 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8821 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};
8822 ofs << " <" << getVTKDataSetType() << ">\n";
8823 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8824 ofs << " <PointData>\n" << pointData << std::endl;
8825 ofs << " </PointData>\n";
8826 ofs << " <CellData>\n" << cellData << std::endl;
8827 ofs << " </CellData>\n";
8828 ofs << " <Points>\n";
8829 if(getSpaceDimension()==3)
8830 _coords->writeVTK(ofs,8,"Points",byteData);
8833 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8834 coo->writeVTK(ofs,8,"Points",byteData);
8836 ofs << " </Points>\n";
8837 ofs << " <Cells>\n";
8838 const int *cPtr=_nodal_connec->getConstPointer();
8839 const int *cIPtr=_nodal_connec_index->getConstPointer();
8840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8844 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8845 int szFaceOffsets=0,szConn=0;
8846 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8849 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8852 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8853 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8857 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8858 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8859 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8860 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8861 w4=std::copy(c.begin(),c.end(),w4);
8864 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8865 types->writeVTK(ofs,8,"UInt8","types",byteData);
8866 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8867 if(szFaceOffsets!=0)
8868 {//presence of Polyhedra
8869 connectivity->reAlloc(szConn);
8870 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8872 w1=faces->getPointer();
8873 for(int i=0;i<nbOfCells;i++)
8874 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8876 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8878 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8879 for(int j=0;j<nbFaces;j++)
8881 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8882 *w1++=(int)std::distance(w6,w5);
8883 w1=std::copy(w6,w5,w1);
8887 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8889 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8890 ofs << " </Cells>\n";
8891 ofs << " </Piece>\n";
8892 ofs << " </" << getVTKDataSetType() << ">\n";
8895 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8897 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8899 { stream << " Not set !"; return ; }
8900 stream << " Mesh dimension : " << _mesh_dim << ".";
8904 { stream << " No coordinates set !"; return ; }
8905 if(!_coords->isAllocated())
8906 { stream << " Coordinates set but not allocated !"; return ; }
8907 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8908 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8909 if(!_nodal_connec_index)
8910 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8911 if(!_nodal_connec_index->isAllocated())
8912 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8913 int lgth=_nodal_connec_index->getNumberOfTuples();
8914 int cpt=_nodal_connec_index->getNumberOfComponents();
8915 if(cpt!=1 || lgth<1)
8917 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8920 std::string MEDCouplingUMesh::getVTKDataSetType() const
8922 return std::string("UnstructuredGrid");
8925 std::string MEDCouplingUMesh::getVTKFileExtension() const
8927 return std::string("vtu");
8931 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8932 * returns a result mesh constituted by polygons.
8933 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8934 * all nodes from m2.
8935 * The meshes should be in 2D space. In
8936 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8938 * \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
8939 * 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)
8940 * \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
8941 * 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)
8942 * \param [in] eps - precision used to detect coincident mesh entities.
8943 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8944 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8945 * this array using decrRef() as it is no more needed.
8946 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8947 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8948 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8949 * any cell of \a m2. The caller is to delete this array using decrRef() as
8950 * it is no more needed.
8951 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8952 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8953 * is no more needed.
8954 * \throw If the coordinates array is not set in any of the meshes.
8955 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8956 * \throw If any of the meshes is not a 2D mesh in 2D space.
8958 * \sa conformize2D, mergeNodes
8960 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8961 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8964 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8965 m1->checkFullyDefined();
8966 m2->checkFullyDefined();
8967 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8968 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8970 // Step 1: compute all edge intersections (new nodes)
8971 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8972 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8973 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8974 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8975 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8976 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8977 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8978 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8980 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8982 // Step 2: re-order newly created nodes according to the ordering found in m2
8983 std::vector< std::vector<int> > intersectEdge2;
8984 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8985 subDiv2.clear(); dd5=0; dd6=0;
8988 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8989 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8990 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8991 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8993 // Step 4: Prepare final result:
8994 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8995 addCooDa->alloc((int)(addCoo.size())/2,2);
8996 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8997 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8998 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8999 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9000 std::vector<const DataArrayDouble *> coordss(4);
9001 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9002 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9003 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9004 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9005 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9006 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9007 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9008 ret->setConnectivity(conn,connI,true);
9009 ret->setCoords(coo);
9010 cellNb1=c1.retn(); cellNb2=c2.retn();
9016 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9018 if(candidates.empty())
9020 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9022 const std::vector<int>& pool(intersectEdge1[*it]);
9023 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9024 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9029 tmp[0]=stop; tmp[1]=start;
9030 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9039 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,
9040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9042 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9043 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9044 int nCells(mesh1D->getNumberOfCells());
9045 if(nCells!=(int)intersectEdge2.size())
9046 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9047 const DataArrayDouble *coo2(mesh1D->getCoords());
9048 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9049 const double *coo2Ptr(coo2->begin());
9050 int offset1(coords1->getNumberOfTuples());
9051 int offset2(offset1+coo2->getNumberOfTuples());
9052 int offset3(offset2+addCoo.size()/2);
9053 std::vector<double> addCooQuad;
9054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9055 int tmp[4],cicnt(0),kk(0);
9056 for(int i=0;i<nCells;i++)
9058 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9059 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9060 const std::vector<int>& subEdges(intersectEdge2[i]);
9061 int nbSubEdge(subEdges.size()/2);
9062 for(int j=0;j<nbSubEdge;j++,kk++)
9064 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));
9065 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9066 INTERP_KERNEL::Edge *e2Ptr(e2);
9067 std::map<int,int>::const_iterator itm;
9068 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9070 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9071 itm=mergedNodes.find(subEdges[2*j]);
9072 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9073 itm=mergedNodes.find(subEdges[2*j+1]);
9074 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9075 tmp[3]=offset3+(int)addCooQuad.size()/2;
9077 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9079 cOut->insertAtTheEnd(tmp,tmp+4);
9080 ciOut->pushBackSilent(cicnt);
9084 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9085 itm=mergedNodes.find(subEdges[2*j]);
9086 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9087 itm=mergedNodes.find(subEdges[2*j+1]);
9088 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9090 cOut->insertAtTheEnd(tmp,tmp+3);
9091 ciOut->pushBackSilent(cicnt);
9094 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9096 idsInRetColinear->pushBackSilent(kk);
9097 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9103 ret->setConnectivity(cOut,ciOut,true);
9104 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9105 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9106 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9107 std::vector<const DataArrayDouble *> coordss(4);
9108 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9109 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9110 ret->setCoords(arr);
9114 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9116 std::vector<int> allEdges;
9117 for(const int *it2(descBg);it2!=descEnd;it2++)
9119 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9121 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9123 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9125 std::size_t nb(allEdges.size());
9127 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9128 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9129 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9130 ret->setCoords(coords);
9131 ret->allocateCells(1);
9132 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9133 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9134 connOut[kk]=allEdges[2*kk];
9135 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9139 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9141 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9142 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9144 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9145 if(sz!=std::distance(descBg,descEnd))
9146 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9147 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9148 std::vector<int> allEdges,centers;
9149 const double *coordsPtr(coords->begin());
9150 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9151 int offset(coords->getNumberOfTuples());
9152 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9154 INTERP_KERNEL::NormalizedCellType typeOfSon;
9155 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9156 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9158 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9160 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9162 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9164 {//the current edge has been subsplit -> create corresponding centers.
9165 std::size_t nbOfCentersToAppend(edge1.size()/2);
9166 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9167 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9168 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9169 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9172 const double *aa(coordsPtr+2*(*it3++));
9173 const double *bb(coordsPtr+2*(*it3++));
9174 ee->getMiddleOfPoints(aa,bb,tmpp);
9175 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9176 centers.push_back(offset+k);
9180 std::size_t nb(allEdges.size());
9182 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9183 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9184 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9186 ret->setCoords(coords);
9189 addCoo->rearrange(2);
9190 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9191 ret->setCoords(addCoo);
9193 ret->allocateCells(1);
9194 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9195 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9196 connOut[kk]=allEdges[2*kk];
9197 connOut.insert(connOut.end(),centers.begin(),centers.end());
9198 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9203 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9206 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9208 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9210 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9211 if(!cm.isQuadratic())
9212 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9214 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9217 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9220 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9222 const INTERP_KERNEL::Edge *ee(*it);
9223 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9227 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9230 const double *coo(mesh2D->getCoords()->begin());
9231 std::size_t sz(conn.size());
9232 std::vector<double> addCoo;
9233 std::vector<int> conn2(conn);
9234 int offset(mesh2D->getNumberOfNodes());
9235 for(std::size_t i=0;i<sz;i++)
9238 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9239 addCoo.insert(addCoo.end(),tmp,tmp+2);
9240 conn2.push_back(offset+(int)i);
9242 mesh2D->getCoords()->rearrange(1);
9243 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9244 mesh2D->getCoords()->rearrange(2);
9245 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9250 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9252 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9253 * a set of edges defined in \a splitMesh1D.
9255 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9256 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9258 std::size_t nb(edge1Bis.size()/2);
9259 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9260 int iEnd(splitMesh1D->getNumberOfCells());
9262 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9264 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9265 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9266 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9269 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9270 out0.resize(1); out1.resize(1);
9271 std::vector<int>& connOut(out0[0]);
9272 connOut.resize(nbOfEdgesOf2DCellSplit);
9273 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9274 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9275 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9277 connOut[kk]=edge1Bis[2*kk];
9278 edgesPtr[kk]=edge1BisPtr[2*kk];
9283 // [i,iEnd[ contains the
9284 out0.resize(2); out1.resize(2);
9285 std::vector<int>& connOutLeft(out0[0]);
9286 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9287 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9288 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9289 for(std::size_t k=ii;k<jj+1;k++)
9290 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9291 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9292 for(int ik=0;ik<iEnd;ik++)
9294 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9295 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9298 for(int ik=iEnd-1;ik>=0;ik--)
9299 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9300 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9301 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9302 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9303 for(int ik=0;ik<iEnd;ik++)
9304 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9305 eright.insert(eright.end(),ees.begin(),ees.end());
9317 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9319 std::vector<int> _edges;
9320 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9323 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9325 std::size_t nbe(edges.size());
9326 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9327 for(std::size_t i=0;i<nbe;i++)
9329 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9330 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9332 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9333 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9334 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9340 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9341 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9342 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9343 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9344 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9348 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9349 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9354 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9356 const MEDCouplingUMesh *mesh(_mesh);
9362 { _left++; _right++; return ; }
9365 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9366 if((isLeft && isRight) || (!isLeft && !isRight))
9367 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9378 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9379 if((isLeft && isRight) || (!isLeft && !isRight))
9380 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9395 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9397 const MEDCouplingUMesh *mesh(_mesh);
9400 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9403 {// not fully splitting cell case
9404 if(mesh2D->getNumberOfCells()==1)
9405 {//little optimization. 1 cell no need to find in which cell mesh is !
9406 neighbors[0]=offset; neighbors[1]=offset;
9411 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9412 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9414 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9415 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9420 class VectorOfCellInfo
9423 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9424 std::size_t size() const { return _pool.size(); }
9425 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9426 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);
9427 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9428 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9429 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9430 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9432 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9433 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9434 const CellInfo& get(int pos) const;
9435 CellInfo& get(int pos);
9437 std::vector<CellInfo> _pool;
9438 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9439 std::vector<EdgeInfo> _edge_info;
9442 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9444 _pool[0]._edges=edges;
9445 _pool[0]._edges_ptr=edgesPtr;
9448 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9451 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9454 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9456 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9457 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9458 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9461 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)
9463 get(pos);//to check pos
9464 bool isFast(pos==0 && _pool.size()==1);
9465 std::size_t sz(edges.size());
9466 // dealing with edges
9468 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9470 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9472 std::vector<CellInfo> pool(_pool.size()-1+sz);
9473 for(int i=0;i<pos;i++)
9475 for(std::size_t j=0;j<sz;j++)
9476 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9477 for(int i=pos+1;i<(int)_pool.size();i++)
9478 pool[i+sz-1]=_pool[i];
9482 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9490 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9493 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9497 if(pos<_ze_mesh->getNumberOfCells()-1)
9499 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9502 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9503 for(std::size_t j=0;j<ms2.size();j++)
9505 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9508 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9510 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9513 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9516 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9518 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9520 if((*it).isInMyRange(pos))
9523 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9526 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9528 get(pos);//to check;
9529 if(_edge_info.empty())
9531 std::size_t sz(_edge_info.size()-1);
9532 for(std::size_t i=0;i<sz;i++)
9533 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9536 const CellInfo& VectorOfCellInfo::get(int pos) const
9538 if(pos<0 || pos>=(int)_pool.size())
9539 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9543 CellInfo& VectorOfCellInfo::get(int pos)
9545 if(pos<0 || pos>=(int)_pool.size())
9546 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9552 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9553 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9555 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9557 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9559 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9561 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9564 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9565 if(nbCellsInSplitMesh1D==0)
9566 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9567 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9568 std::size_t nb(allEdges.size()),jj;
9570 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9571 std::vector<int> edge1Bis(nb*2);
9572 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9573 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9574 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9575 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9576 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9578 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9579 int *idsLeftRightPtr(idsLeftRight->getPointer());
9580 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9581 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9582 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9584 for(;iEnd<nbCellsInSplitMesh1D;)
9586 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9592 if(iEnd<nbCellsInSplitMesh1D)
9595 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9596 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9598 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9599 retTmp->setCoords(splitMesh1D->getCoords());
9600 retTmp->allocateCells();
9602 std::vector< std::vector<int> > out0;
9603 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9605 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9606 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9607 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9608 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9612 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9613 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9614 return pool.getZeMesh().retn();
9617 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9618 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9619 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9621 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9623 std::vector<int> allEdges;
9624 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9625 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9627 int edgeId(std::abs(*it)-1);
9628 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9629 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9630 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9632 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9634 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9635 std::size_t sz(edge1.size());
9636 for(std::size_t cnt=0;cnt<sz;cnt++)
9637 allEdgesPtr.push_back(ee);
9640 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9643 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9645 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9646 {//easy case comparison not
9647 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9649 else if(typ1.isQuadratic() && typ2.isQuadratic())
9651 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9654 if(conn1[2]==conn2[2])
9656 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9657 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9661 {//only one is quadratic
9662 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9665 const double *a(0),*bb(0),*be(0);
9666 if(typ1.isQuadratic())
9668 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9672 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9674 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9675 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9681 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9682 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9684 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9686 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9688 if(candidatesIn2DEnd==candidatesIn2DBg)
9689 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9690 const double *coo(mesh2DSplit->getCoords()->begin());
9691 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9692 return *candidatesIn2DBg;
9693 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9694 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9695 if(cellIdInMesh1DSplitRelative<0)
9696 cur1D->changeOrientationOfCells();
9697 const int *c1D(cur1D->getNodalConnectivity()->begin());
9698 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9699 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9701 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9702 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9703 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9704 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9705 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9706 for(unsigned it2=0;it2<sz;it2++)
9708 INTERP_KERNEL::NormalizedCellType typeOfSon;
9709 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9710 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9711 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9715 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9721 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9722 * 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
9723 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9724 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9726 * \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
9727 * 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)
9728 * \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
9729 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9730 * \param [in] eps - precision used to perform intersections and localization operations.
9731 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9732 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9733 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9734 * 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.
9735 * \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
9736 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9737 * 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.
9739 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9741 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9743 if(!mesh2D || !mesh1D)
9744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9745 mesh2D->checkFullyDefined();
9746 mesh1D->checkFullyDefined();
9747 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9748 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9749 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9750 // Step 1: compute all edge intersections (new nodes)
9751 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9752 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9753 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9754 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9756 // Build desc connectivity
9757 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9759 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9760 std::map<int,int> mergedNodes;
9761 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9762 // use mergeNodes to fix intersectEdge1
9763 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9765 std::size_t n((*it0).size()/2);
9766 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9767 std::map<int,int>::const_iterator it1;
9768 it1=mergedNodes.find(eltStart);
9769 if(it1!=mergedNodes.end())
9770 (*it0)[0]=(*it1).second;
9771 it1=mergedNodes.find(eltEnd);
9772 if(it1!=mergedNodes.end())
9773 (*it0)[2*n-1]=(*it1).second;
9776 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9777 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9778 // Step 2: re-order newly created nodes according to the ordering found in m2
9779 std::vector< std::vector<int> > intersectEdge2;
9780 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9782 // Step 3: compute splitMesh1D
9783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9785 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9786 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9788 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9789 // deal with cells in mesh2D that are not cut but only some of their edges are
9790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9791 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9792 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9793 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
9794 if(!idsInDesc2DToBeRefined->empty())
9796 DataArrayInt *out0(0),*outi0(0);
9797 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9798 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9800 out0s=out0s->buildUnique();
9804 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9805 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9806 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9807 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9810 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9811 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9814 if((DataArrayInt *)out0s)
9815 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9816 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9817 // OK all is ready to insert in ret2 mesh
9818 if(!untouchedCells->empty())
9819 {// the most easy part, cells in mesh2D not impacted at all
9820 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9821 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9822 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9824 if((DataArrayInt *)out0s)
9825 {// here dealing with cells in out0s but not in cellsToBeModified
9826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9827 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9828 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9830 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9831 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9833 int offset(ret2->getNumberOfTuples());
9834 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9836 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9837 int kk(0),*ret3ptr(partOfRet3->getPointer());
9838 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9840 int faceId(std::abs(*it)-1);
9841 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9843 int tmp(fewModifiedCells->locateValue(*it2));
9846 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9847 ret3ptr[2*kk]=tmp+offset;
9848 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9849 ret3ptr[2*kk+1]=tmp+offset;
9852 {//the current edge is shared by a 2D cell that will be split just after
9853 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9854 ret3ptr[2*kk]=-(*it2+1);
9855 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9856 ret3ptr[2*kk+1]=-(*it2+1);
9860 m1Desc->setCoords(ret1->getCoords());
9861 ret1NonCol->setCoords(ret1->getCoords());
9862 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9863 if(!outMesh2DSplit.empty())
9865 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9866 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9867 (*itt)->setCoords(da);
9870 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9871 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9874 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9876 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9878 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));
9879 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9880 outMesh2DSplit.push_back(splitOfOneCell);
9881 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9882 ret2->pushBackSilent(*it);
9885 std::size_t nbOfMeshes(outMesh2DSplit.size());
9886 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9887 for(std::size_t i=0;i<nbOfMeshes;i++)
9888 tmp[i]=outMesh2DSplit[i];
9890 ret1->getCoords()->setInfoOnComponents(compNames);
9891 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9892 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9895 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9897 int old2DCellId(-ret3->getIJ(*it,0)-1);
9898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9899 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
9901 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9904 splitMesh1D=ret1.retn();
9905 splitMesh2D=ret2D.retn();
9906 cellIdInMesh2D=ret2.retn();
9907 cellIdInMesh1D=ret3.retn();
9911 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9912 * (newly created) nodes corresponding to the edge intersections.
9914 * @param[out] cr, crI connectivity of the resulting mesh
9915 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9916 * TODO: describe input parameters
9918 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9919 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9920 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9921 const std::vector<double>& addCoords,
9922 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9924 static const int SPACEDIM=2;
9925 const double *coo1(m1->getCoords()->getConstPointer());
9926 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9927 int offset1(m1->getNumberOfNodes());
9928 const double *coo2(m2->getCoords()->getConstPointer());
9929 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9930 int offset2(offset1+m2->getNumberOfNodes());
9931 int offset3(offset2+((int)addCoords.size())/2);
9932 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9933 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9934 // Here a BBTree on 2D-cells, not on segments:
9935 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9936 int ncell1(m1->getNumberOfCells());
9938 for(int i=0;i<ncell1;i++)
9940 std::vector<int> candidates2;
9941 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9942 std::map<INTERP_KERNEL::Node *,int> mapp;
9943 std::map<int,INTERP_KERNEL::Node *> mappRev;
9944 INTERP_KERNEL::QuadraticPolygon pol1;
9945 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9946 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9947 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9948 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9949 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9950 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9951 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9953 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
9954 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9955 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9956 for(it1.first();!it1.finished();it1.next())
9957 edges1.insert(it1.current()->getPtr());
9959 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9960 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9962 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9964 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9965 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9966 // Complete mapping with elements coming from the current cell it2 in mesh2:
9967 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9968 // pol2 is the new QP in the final merged result.
9969 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9970 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9973 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9975 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9976 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9977 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9978 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9980 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9981 // by m2 but that we still want to keep in the final result.
9986 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9988 catch(INTERP_KERNEL::Exception& e)
9990 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();
9991 throw INTERP_KERNEL::Exception(oss.str().c_str());
9994 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9995 (*it).second->decrRef();
10000 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10001 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10002 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10003 * The caller is to deal with the resulting DataArrayInt.
10004 * \throw If the coordinate array is not set.
10005 * \throw If the nodal connectivity of the cells is not defined.
10006 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10007 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10009 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10011 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10013 checkFullyDefined();
10014 if(getMeshDimension()!=1)
10015 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10017 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10019 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10020 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10021 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10022 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10024 const int * dsi(_dsi->getConstPointer());
10025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10027 if (dsii->getNumberOfTuples())
10028 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10030 int nc(getNumberOfCells());
10031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10032 result->alloc(nc,1);
10034 // set of edges not used so far
10035 std::set<int> edgeSet;
10036 for (int i=0; i<nc; edgeSet.insert(i), i++);
10040 // while we have points with only one neighbor segments
10043 std::list<int> linePiece;
10044 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10045 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10047 // Fill the list forward (resp. backward) from the start segment:
10048 int activeSeg = startSeg;
10049 int prevPointId = -20;
10051 while (!edgeSet.empty())
10053 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10056 linePiece.push_back(activeSeg);
10058 linePiece.push_front(activeSeg);
10059 edgeSet.erase(activeSeg);
10062 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10063 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10064 if (dsi[ptId] == 1) // hitting the end of the line
10066 prevPointId = ptId;
10067 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10068 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10071 // Done, save final piece into DA:
10072 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10073 newIdx += linePiece.size();
10075 // identify next valid start segment (one which is not consumed)
10076 if(!edgeSet.empty())
10077 startSeg = *(edgeSet.begin());
10079 while (!edgeSet.empty());
10080 return result.retn();
10085 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10087 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10088 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10090 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10091 int v((*it).second);
10092 if(v==forbVal0 || v==forbVal1)
10094 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10095 isect.push_back(v);
10098 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10103 bool presenceOfOn(false);
10104 for(int i=0;i<sz;i++)
10106 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10107 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10109 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10110 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10112 return presenceOfOn;
10118 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
10119 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
10120 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
10121 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10123 * \return int - the number of new nodes created (in most of cases 0).
10125 * \throw If \a this is not coherent.
10126 * \throw If \a this has not spaceDim equal to 2.
10127 * \throw If \a this has not meshDim equal to 2.
10128 * \throw If some subcells needed to be split are orphan.
10129 * \sa MEDCouplingUMesh::conformize2D
10131 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10133 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10134 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10135 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10136 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10137 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10138 if(midOpt==0 && midOptI==0)
10140 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10143 else if(midOpt!=0 && midOptI!=0)
10144 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10146 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10150 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10151 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10152 * 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
10153 * 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).
10154 * 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.
10156 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10157 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10159 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10160 * This method expects that all nodes in \a this are not closer than \a eps.
10161 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10163 * \param [in] eps the relative error to detect merged edges.
10164 * \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
10165 * that the user is expected to deal with.
10167 * \throw If \a this is not coherent.
10168 * \throw If \a this has not spaceDim equal to 2.
10169 * \throw If \a this has not meshDim equal to 2.
10170 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10172 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10174 static const int SPACEDIM=2;
10176 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10177 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10179 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10180 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10181 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10182 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10183 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10184 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10185 std::vector<double> addCoo;
10186 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10187 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10188 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10189 for(int i=0;i<nDescCell;i++)
10191 std::vector<int> candidates;
10192 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10193 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10196 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10197 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10198 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10199 INTERP_KERNEL::MergePoints merge;
10200 INTERP_KERNEL::QuadraticPolygon c1,c2;
10201 e1->intersectWith(e2,merge,c1,c2);
10202 e1->decrRef(); e2->decrRef();
10203 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10204 overlapEdge[i].push_back(*it);
10205 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10206 overlapEdge[*it].push_back(i);
10209 // splitting done. sort intersect point in intersectEdge.
10210 std::vector< std::vector<int> > middle(nDescCell);
10211 int nbOf2DCellsToBeSplit(0);
10212 bool middleNeedsToBeUsed(false);
10213 std::vector<bool> cells2DToTreat(nDescCell,false);
10214 for(int i=0;i<nDescCell;i++)
10216 std::vector<int>& isect(intersectEdge[i]);
10217 int sz((int)isect.size());
10220 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10221 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10222 e->sortSubNodesAbs(coords,isect);
10227 int idx0(rdi[i]),idx1(rdi[i+1]);
10229 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10230 if(!cells2DToTreat[rd[idx0]])
10232 cells2DToTreat[rd[idx0]]=true;
10233 nbOf2DCellsToBeSplit++;
10235 // try to reuse at most eventual 'middle' of SEG3
10236 std::vector<int>& mid(middle[i]);
10237 mid.resize(sz+1,-1);
10238 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10240 middleNeedsToBeUsed=true;
10241 const std::vector<int>& candidates(overlapEdge[i]);
10242 std::vector<int> trueCandidates;
10243 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10244 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10245 trueCandidates.push_back(*itc);
10246 int stNode(c[ci[i]+1]),endNode(isect[0]);
10247 for(int j=0;j<sz+1;j++)
10249 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10251 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10252 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10253 { mid[j]=*itc; break; }
10256 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10262 if(nbOf2DCellsToBeSplit==0)
10265 int *retPtr(ret->getPointer());
10266 for(int i=0;i<nCell;i++)
10267 if(cells2DToTreat[i])
10270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10271 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10272 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10273 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10274 if(middleNeedsToBeUsed)
10275 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10276 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10277 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10278 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.
10279 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10281 bool areNodesMerged; int newNbOfNodes;
10282 if(nbOfNodesCreated!=0)
10283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10289 * 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.
10290 * 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).
10291 * 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
10292 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10293 * 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
10294 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10296 * 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
10297 * using new instance, idem for coordinates.
10299 * 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.
10301 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10303 * \throw If \a this is not coherent.
10304 * \throw If \a this has not spaceDim equal to 2.
10305 * \throw If \a this has not meshDim equal to 2.
10307 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10309 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10313 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10314 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10315 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10316 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10317 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10318 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10320 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10321 const double *coords(_coords->begin());
10322 int *newciptr(newci->getPointer());
10323 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10325 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10326 ret->pushBackSilent(i);
10327 newciptr[1]=newc->getNumberOfTuples();
10332 if(!appendedCoords->empty())
10334 appendedCoords->rearrange(2);
10335 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10337 setCoords(newCoords);
10340 setConnectivity(newc,newci,true);
10345 * \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.
10346 * 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.
10347 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10348 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10349 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10350 * \param [out] addCoo - nodes to be append at the end
10351 * \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.
10353 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10354 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)
10356 static const int SPACEDIM=2;
10357 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10358 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10359 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10360 // Build BB tree of all edges in the tool mesh (second mesh)
10361 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10362 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10363 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10364 intersectEdge1.resize(nDescCell1);
10365 colinear2.resize(nDescCell2);
10366 subDiv2.resize(nDescCell2);
10367 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10369 std::vector<int> candidates1(1);
10370 int offset1(m1Desc->getNumberOfNodes());
10371 int offset2(offset1+m2Desc->getNumberOfNodes());
10372 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10374 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10375 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10376 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10378 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10379 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10380 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10382 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10383 // 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
10384 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10385 std::set<INTERP_KERNEL::Node *> nodes;
10386 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10387 std::size_t szz(nodes.size());
10388 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10389 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10390 for(std::size_t iii=0;iii<szz;iii++,itt++)
10391 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10392 // end of protection
10393 // Performs egde cutting:
10394 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10399 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10400 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10405 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10406 * It builds the descending connectivity of the two meshes, and then using a binary tree
10407 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10408 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10410 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10411 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10412 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10413 std::vector<double>& addCoo,
10414 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10416 // Build desc connectivity
10417 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10418 desc2=DataArrayInt::New();
10419 descIndx2=DataArrayInt::New();
10420 revDesc2=DataArrayInt::New();
10421 revDescIndx2=DataArrayInt::New();
10422 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10423 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10424 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10425 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10426 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10427 std::map<int,int> notUsedMap;
10428 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10429 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10430 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10434 * This method performs the 2nd step of Partition of 2D mesh.
10435 * This method has 4 inputs :
10436 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10437 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10438 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10439 * 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'
10440 * Nodes end up lying consecutively on a cutted edge.
10441 * \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.
10442 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10443 * \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.
10444 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10445 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10447 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10448 const std::vector<double>& addCoo,
10449 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10451 int offset1=m1->getNumberOfNodes();
10452 int ncell=m2->getNumberOfCells();
10453 const int *c=m2->getNodalConnectivity()->getConstPointer();
10454 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10455 const double *coo=m2->getCoords()->getConstPointer();
10456 const double *cooBis=m1->getCoords()->getConstPointer();
10457 int offset2=offset1+m2->getNumberOfNodes();
10458 intersectEdge.resize(ncell);
10459 for(int i=0;i<ncell;i++,cI++)
10461 const std::vector<int>& divs=subDiv[i];
10462 int nnode=cI[1]-cI[0]-1;
10463 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10464 std::map<INTERP_KERNEL::Node *, int> mapp22;
10465 for(int j=0;j<nnode;j++)
10467 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10468 int nnid=c[(*cI)+j+1];
10469 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10470 mapp22[nn]=nnid+offset1;
10472 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10473 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10474 ((*it).second.first)->decrRef();
10475 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10476 std::map<INTERP_KERNEL::Node *,int> mapp3;
10477 for(std::size_t j=0;j<divs.size();j++)
10480 INTERP_KERNEL::Node *tmp=0;
10482 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10483 else if(id<offset2)
10484 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10486 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10490 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10491 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10498 * 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).
10499 * 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
10500 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10501 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10502 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10503 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10504 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10505 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10506 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10507 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10508 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10509 * \param [out] cut3DSuf input/output param.
10511 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10512 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10513 const int *desc, const int *descIndx,
10514 std::vector< std::pair<int,int> >& cut3DSurf)
10516 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10517 int nbOf3DSurfCell=(int)cut3DSurf.size();
10518 for(int i=0;i<nbOf3DSurfCell;i++)
10520 std::vector<int> res;
10521 int offset=descIndx[i];
10522 int nbOfSeg=descIndx[i+1]-offset;
10523 for(int j=0;j<nbOfSeg;j++)
10525 int edgeId=desc[offset+j];
10526 int status=cut3DCurve[edgeId];
10530 res.push_back(status);
10533 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10534 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10542 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10548 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10549 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10552 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10556 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10561 {// case when plane is on a multi colinear edge of a polyhedron
10562 if((int)res.size()==2*nbOfSeg)
10564 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10567 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10574 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10575 * 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).
10576 * 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
10577 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10578 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10579 * \param desc is the descending connectivity 3D->3DSurf
10580 * \param descIndx is the descending connectivity index 3D->3DSurf
10582 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10583 const int *desc, const int *descIndx,
10584 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10586 checkFullyDefined();
10587 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10588 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10589 const int *nodal3D=_nodal_connec->getConstPointer();
10590 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10591 int nbOfCells=getNumberOfCells();
10592 for(int i=0;i<nbOfCells;i++)
10594 std::map<int, std::set<int> > m;
10595 int offset=descIndx[i];
10596 int nbOfFaces=descIndx[i+1]-offset;
10599 for(int j=0;j<nbOfFaces;j++)
10601 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10602 if(p.first!=-1 && p.second!=-1)
10606 start=p.first; end=p.second;
10607 m[p.first].insert(p.second);
10608 m[p.second].insert(p.first);
10612 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10613 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10614 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10615 INTERP_KERNEL::NormalizedCellType cmsId;
10616 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10617 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10618 for(unsigned k=0;k<nbOfNodesSon;k++)
10620 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10621 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10628 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10632 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10633 const std::set<int>& s=(*it).second;
10634 std::set<int> s2; s2.insert(prev);
10636 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10639 int val=*s3.begin();
10640 conn.push_back(start);
10647 conn.push_back(end);
10650 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10651 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10652 cellIds->pushBackSilent(i);
10658 * 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
10659 * 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
10660 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10661 * 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
10662 * 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.
10664 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10666 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10668 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10671 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10672 if(cm.getDimension()==2)
10674 const int *node=nodalConnBg+1;
10675 int startNode=*node++;
10676 double refX=coords[2*startNode];
10677 for(;node!=nodalConnEnd;node++)
10679 if(coords[2*(*node)]<refX)
10682 refX=coords[2*startNode];
10685 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10689 double angle0=-M_PI/2;
10694 double angleNext=0.;
10695 while(nextNode!=startNode)
10699 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10701 if(*node!=tmpOut.back() && *node!=prevNode)
10703 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10704 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10709 res=angle0-angleM+2.*M_PI;
10718 if(nextNode!=startNode)
10720 angle0=angleNext-M_PI;
10723 prevNode=tmpOut.back();
10724 tmpOut.push_back(nextNode);
10727 std::vector<int> tmp3(2*(sz-1));
10728 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10729 std::copy(nodalConnBg+1,nodalConnEnd,it);
10730 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10732 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10735 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10737 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10742 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10743 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10751 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10755 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10756 * 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.
10758 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10759 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10760 * \param [in,out] arr array in which the remove operation will be done.
10761 * \param [in,out] arrIndx array in the remove operation will modify
10762 * \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])
10763 * \return true if \b arr and \b arrIndx have been modified, false if not.
10765 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10767 if(!arrIndx || !arr)
10768 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10769 if(offsetForRemoval<0)
10770 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10771 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10772 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10773 int *arrIPtr=arrIndx->getPointer();
10775 int previousArrI=0;
10776 const int *arrPtr=arr->getConstPointer();
10777 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10778 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10780 if(*arrIPtr-previousArrI>offsetForRemoval)
10782 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10784 if(s.find(*work)==s.end())
10785 arrOut.push_back(*work);
10788 previousArrI=*arrIPtr;
10789 *arrIPtr=(int)arrOut.size();
10791 if(arr->getNumberOfTuples()==(int)arrOut.size())
10793 arr->alloc((int)arrOut.size(),1);
10794 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10799 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10800 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10801 * The selection of extraction is done standardly in new2old format.
10802 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10804 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10805 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10806 * \param [in] arrIn arr origin array from which the extraction will be done.
10807 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10808 * \param [out] arrOut the resulting array
10809 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10810 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10812 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10813 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10815 if(!arrIn || !arrIndxIn)
10816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10817 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10818 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10819 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10820 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10821 const int *arrInPtr=arrIn->getConstPointer();
10822 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10823 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10825 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10826 int maxSizeOfArr=arrIn->getNumberOfTuples();
10827 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10829 arrIo->alloc((int)(sz+1),1);
10830 const int *idsIt=idsOfSelectBg;
10831 int *work=arrIo->getPointer();
10834 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10836 if(*idsIt>=0 && *idsIt<nbOfGrps)
10837 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10840 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10841 throw INTERP_KERNEL::Exception(oss.str().c_str());
10847 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10848 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10849 throw INTERP_KERNEL::Exception(oss.str().c_str());
10852 arro->alloc(lgth,1);
10853 work=arro->getPointer();
10854 idsIt=idsOfSelectBg;
10855 for(std::size_t i=0;i<sz;i++,idsIt++)
10857 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10858 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10861 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10862 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10863 throw INTERP_KERNEL::Exception(oss.str().c_str());
10866 arrOut=arro.retn();
10867 arrIndexOut=arrIo.retn();
10871 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10872 * 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 ).
10873 * The selection of extraction is done standardly in new2old format.
10874 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10876 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10877 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10878 * \param [in] arrIn arr origin array from which the extraction will be done.
10879 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10880 * \param [out] arrOut the resulting array
10881 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10882 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10884 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10885 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10887 if(!arrIn || !arrIndxIn)
10888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10889 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10890 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10892 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10893 const int *arrInPtr=arrIn->getConstPointer();
10894 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10895 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10898 int maxSizeOfArr=arrIn->getNumberOfTuples();
10899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10900 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10901 arrIo->alloc((int)(sz+1),1);
10902 int idsIt=idsOfSelectStart;
10903 int *work=arrIo->getPointer();
10906 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10908 if(idsIt>=0 && idsIt<nbOfGrps)
10909 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10912 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10913 throw INTERP_KERNEL::Exception(oss.str().c_str());
10919 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10920 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10921 throw INTERP_KERNEL::Exception(oss.str().c_str());
10924 arro->alloc(lgth,1);
10925 work=arro->getPointer();
10926 idsIt=idsOfSelectStart;
10927 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10929 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10930 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10933 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10934 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10935 throw INTERP_KERNEL::Exception(oss.str().c_str());
10938 arrOut=arro.retn();
10939 arrIndexOut=arrIo.retn();
10943 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10944 * 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
10945 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10946 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10948 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10949 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10950 * \param [in] arrIn arr origin array from which the extraction will be done.
10951 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10952 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10953 * \param [in] srcArrIndex index array of \b srcArr
10954 * \param [out] arrOut the resulting array
10955 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10957 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10959 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10960 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10961 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10963 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10964 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10966 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10967 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10968 std::vector<bool> v(nbOfTuples,true);
10970 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10971 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10972 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10974 if(*it>=0 && *it<nbOfTuples)
10977 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10981 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10982 throw INTERP_KERNEL::Exception(oss.str().c_str());
10985 srcArrIndexPtr=srcArrIndex->getConstPointer();
10986 arrIo->alloc(nbOfTuples+1,1);
10987 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10988 const int *arrInPtr=arrIn->getConstPointer();
10989 const int *srcArrPtr=srcArr->getConstPointer();
10990 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10991 int *arroPtr=arro->getPointer();
10992 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10996 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10997 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11001 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11002 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11003 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11006 arrOut=arro.retn();
11007 arrIndexOut=arrIo.retn();
11011 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11012 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11014 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11015 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11016 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11017 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11018 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11019 * \param [in] srcArrIndex index array of \b srcArr
11021 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11023 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11024 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11026 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11027 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11028 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11029 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11030 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11031 int *arrInOutPtr=arrInOut->getPointer();
11032 const int *srcArrPtr=srcArr->getConstPointer();
11033 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11035 if(*it>=0 && *it<nbOfTuples)
11037 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11038 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11041 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] !";
11042 throw INTERP_KERNEL::Exception(oss.str().c_str());
11047 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11048 throw INTERP_KERNEL::Exception(oss.str().c_str());
11054 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11055 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11056 * 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]].
11057 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11058 * A negative value in \b arrIn means that it is ignored.
11059 * 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.
11061 * \param [in] arrIn arr origin array from which the extraction will be done.
11062 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11063 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11064 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11066 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11068 int seed=0,nbOfDepthPeelingPerformed=0;
11069 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11073 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11074 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11075 * 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]].
11076 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11077 * A negative value in \b arrIn means that it is ignored.
11078 * 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.
11079 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11080 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11081 * \param [in] arrIn arr origin array from which the extraction will be done.
11082 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11083 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11084 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11085 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11086 * \sa MEDCouplingUMesh::partitionBySpreadZone
11088 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11090 nbOfDepthPeelingPerformed=0;
11092 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11093 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11096 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11100 std::vector<bool> fetched(nbOfTuples,false);
11101 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11104 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11106 nbOfDepthPeelingPerformed=0;
11107 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11108 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11109 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11110 std::vector<bool> fetched2(nbOfTuples,false);
11112 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11114 if(*seedElt>=0 && *seedElt<nbOfTuples)
11115 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11117 { 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()); }
11119 const int *arrInPtr=arrIn->getConstPointer();
11120 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11121 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11122 std::vector<int> idsToFetch1(seedBg,seedEnd);
11123 std::vector<int> idsToFetch2;
11124 std::vector<int> *idsToFetch=&idsToFetch1;
11125 std::vector<int> *idsToFetchOther=&idsToFetch2;
11126 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11128 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11129 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11131 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11132 std::swap(idsToFetch,idsToFetchOther);
11133 idsToFetchOther->clear();
11134 nbOfDepthPeelingPerformed++;
11136 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11139 int *retPtr=ret->getPointer();
11140 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11147 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11148 * 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
11149 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11150 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11152 * \param [in] start begin of set of ids of the input extraction (included)
11153 * \param [in] end end of set of ids of the input extraction (excluded)
11154 * \param [in] step step of the set of ids in range mode.
11155 * \param [in] arrIn arr origin array from which the extraction will be done.
11156 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11157 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11158 * \param [in] srcArrIndex index array of \b srcArr
11159 * \param [out] arrOut the resulting array
11160 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11162 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11164 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11165 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11166 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11168 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11169 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11170 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11172 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11174 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11175 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11176 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11178 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11180 if(it>=0 && it<nbOfTuples)
11181 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11184 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11185 throw INTERP_KERNEL::Exception(oss.str().c_str());
11188 srcArrIndexPtr=srcArrIndex->getConstPointer();
11189 arrIo->alloc(nbOfTuples+1,1);
11190 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11191 const int *arrInPtr=arrIn->getConstPointer();
11192 const int *srcArrPtr=srcArr->getConstPointer();
11193 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11194 int *arroPtr=arro->getPointer();
11195 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11197 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11200 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11201 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11205 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11206 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11209 arrOut=arro.retn();
11210 arrIndexOut=arrIo.retn();
11214 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11215 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11217 * \param [in] start begin of set of ids of the input extraction (included)
11218 * \param [in] end end of set of ids of the input extraction (excluded)
11219 * \param [in] step step of the set of ids in range mode.
11220 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11221 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11222 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11223 * \param [in] srcArrIndex index array of \b srcArr
11225 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11227 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11228 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11230 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11232 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11233 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11234 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11235 int *arrInOutPtr=arrInOut->getPointer();
11236 const int *srcArrPtr=srcArr->getConstPointer();
11237 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11239 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11241 if(it>=0 && it<nbOfTuples)
11243 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11244 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11247 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11248 throw INTERP_KERNEL::Exception(oss.str().c_str());
11253 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11254 throw INTERP_KERNEL::Exception(oss.str().c_str());
11260 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11261 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11262 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11263 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11264 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11266 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11268 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11270 checkFullyDefined();
11271 int mdim=getMeshDimension();
11272 int spaceDim=getSpaceDimension();
11274 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11275 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11276 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11277 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11278 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11279 ret->setCoords(getCoords());
11280 ret->allocateCells((int)partition.size());
11282 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11284 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11289 cell=tmp->buildUnionOf2DMesh();
11292 cell=tmp->buildUnionOf3DMesh();
11295 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11298 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11301 ret->finishInsertingCells();
11306 * This method partitions \b this into contiguous zone.
11307 * This method only needs a well defined connectivity. Coordinates are not considered here.
11308 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11310 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11312 int nbOfCellsCur=getNumberOfCells();
11313 std::vector<DataArrayInt *> ret;
11314 if(nbOfCellsCur<=0)
11316 DataArrayInt *neigh=0,*neighI=0;
11317 computeNeighborsOfCells(neigh,neighI);
11318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11319 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11320 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11322 while(seed<nbOfCellsCur)
11324 int nbOfPeelPerformed=0;
11325 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11326 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11328 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11329 ret.push_back((*it).retn());
11334 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11335 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11337 * \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.
11338 * \return a newly allocated DataArrayInt to be managed by the caller.
11339 * \throw In case of \a code has not the right format (typically of size 3*n)
11341 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11344 std::size_t nb=code.size()/3;
11345 if(code.size()%3!=0)
11346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11347 ret->alloc((int)nb,2);
11348 int *retPtr=ret->getPointer();
11349 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11351 retPtr[0]=code[3*i+2];
11352 retPtr[1]=code[3*i+2]+code[3*i+1];
11358 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11359 * All cells in \a this are expected to be linear 3D cells.
11360 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11361 * It leads to an increase to number of cells.
11362 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11363 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11364 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11366 * \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.
11367 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11368 * \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.
11369 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11370 * an id of old cell producing it. The caller is to delete this array using
11371 * decrRef() as it is no more needed.
11372 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11374 * \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
11375 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11377 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11378 * \throw If \a this is not fully constituted with linear 3D cells.
11379 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11381 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11383 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11384 checkConnectivityFullyDefined();
11385 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11386 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11387 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11388 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11390 int *retPt(ret->getPointer());
11391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11392 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11393 const int *oldc(_nodal_connec->begin());
11394 const int *oldci(_nodal_connec_index->begin());
11395 const double *coords(_coords->begin());
11396 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11398 std::vector<int> a; std::vector<double> b;
11399 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11400 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11401 const int *aa(&a[0]);
11404 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11406 *it=(-(*(it))-1+nbNodes);
11407 addPts->insertAtTheEnd(b.begin(),b.end());
11408 nbNodes+=(int)b.size()/3;
11410 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11411 newConn->insertAtTheEnd(aa,aa+4);
11413 if(!addPts->empty())
11415 addPts->rearrange(3);
11416 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11417 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11418 ret0->setCoords(addPts);
11422 nbOfAdditionalPoints=0;
11423 ret0->setCoords(getCoords());
11425 ret0->setNodalConnectivity(newConn);
11427 ret->computeOffsets2();
11428 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11429 return ret0.retn();
11433 * 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).
11435 * \sa MEDCouplingUMesh::split2DCells
11437 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11439 checkConnectivityFullyDefined();
11440 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11441 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11442 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11443 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11444 int prevPosOfCi(ciPtr[0]);
11445 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11447 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11448 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11449 for(int j=0;j<sz;j++)
11451 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11452 for(int k=0;k<sz2;k++)
11453 *cPtr++=subPtr[offset2+k];
11455 *cPtr++=oldConn[prevPosOfCi+j+2];
11458 prevPosOfCi=ciPtr[1];
11459 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11463 _nodal_connec->decrRef();
11464 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11467 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11473 int ret(nodesCnter++);
11475 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11476 addCoo.insertAtTheEnd(newPt,newPt+2);
11481 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11487 int ret(nodesCnter++);
11489 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11490 addCoo.insertAtTheEnd(newPt,newPt+2);
11498 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)
11501 int trueStart(start>=0?start:nbOfEdges+start);
11502 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11503 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11508 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11509 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11510 middles.push_back(tmp3+offset);
11513 middles.push_back(connBg[trueStart+nbOfEdges]);
11517 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)
11519 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11520 newConnOfCell->pushBackSilent(tmpEnd);
11525 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11526 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11527 middles.push_back(tmp3+offset);
11530 middles.push_back(connBg[start+nbOfEdges]);
11534 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)
11536 // only the quadratic point to deal with:
11541 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11542 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11543 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11544 middles.push_back(tmp3+offset);
11547 middles.push_back(connBg[start+nbOfEdges]);
11554 * 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 ) .
11555 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11557 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11559 std::size_t sz(std::distance(connBg,connEnd));
11560 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11561 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11563 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11564 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11565 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11566 unsigned nbOfHit(0); // number of fusions operated
11567 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11568 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
11569 INTERP_KERNEL::NormalizedCellType typeOfSon;
11570 std::vector<int> middles;
11572 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11574 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11575 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11576 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11577 posEndElt = posBaseElt+1;
11579 // Look backward first: are the final edges of the cells colinear with the first ones?
11580 // This initializes posBaseElt.
11583 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11585 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11586 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11587 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11588 bool isColinear=eint->areColinears();
11601 // Now move forward:
11602 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11603 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11605 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11606 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11607 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11608 bool isColinear(eint->areColinears());
11620 //push [posBaseElt,posEndElt) in newConnOfCell using e
11621 // 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!
11623 // at the begining of the connectivity (insert type)
11624 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11625 else if((nbOfHit+nbOfTurn) != (nbs-1))
11627 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11628 if ((nbOfHit+nbOfTurn) == (nbs-1))
11629 // at the end (only quad points to deal with)
11630 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11631 posBaseElt=posEndElt;
11634 if(!middles.empty())
11635 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11640 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11642 * \return int - the number of new nodes created.
11643 * \sa MEDCouplingUMesh::split2DCells
11645 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11648 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11649 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11650 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11651 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11652 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11653 const double *oldCoordsPtr(getCoords()->begin());
11654 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11655 int prevPosOfCi(ciPtr[0]);
11656 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11658 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11659 for(int j=0;j<sz;j++)
11660 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11661 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11662 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11664 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11668 cPtr[1]=oldConn[prevPosOfCi+2+j];
11669 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11672 std::vector<INTERP_KERNEL::Node *> ns(3);
11673 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11674 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11675 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11676 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11677 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11679 cPtr[1]=subPtr[offset2+k];
11680 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11682 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11684 { cPtr[1]=tmpEnd; }
11685 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11687 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11688 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11691 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11692 _nodal_connec->decrRef();
11693 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11694 addCoo->rearrange(2);
11695 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11697 return addCoo->getNumberOfTuples();
11700 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11702 if(nodalConnec && nodalConnecIndex)
11705 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11706 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11708 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11709 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11713 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11714 _own_cell(true),_cell_id(-1),_nb_cell(0)
11719 _nb_cell=mesh->getNumberOfCells();
11723 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11731 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11732 _own_cell(false),_cell_id(bg-1),
11739 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11742 if(_cell_id<_nb_cell)
11751 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11757 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11759 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11762 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11768 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11776 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11782 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11787 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11792 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11794 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11797 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11802 _nb_cell=mesh->getNumberOfCells();
11806 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11813 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11815 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11816 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11817 if(_cell_id<_nb_cell)
11819 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11820 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11821 int startId=_cell_id;
11822 _cell_id+=nbOfElems;
11823 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11829 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11833 _conn=mesh->getNodalConnectivity()->getPointer();
11834 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11838 void MEDCouplingUMeshCell::next()
11840 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11845 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11848 std::string MEDCouplingUMeshCell::repr() const
11850 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11852 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11854 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11858 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11861 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11863 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11864 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11866 return INTERP_KERNEL::NORM_ERROR;
11869 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11872 if(_conn_lgth!=NOTICABLE_FIRST_VAL)