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 \b this. The data array returned has to be dealt by the caller.
1400 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1401 * the format of 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 find in \b this cells 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 cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2334 * This method method returns cells ids set s = s1 + s2 where :
2336 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2337 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2339 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2342 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2343 * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2344 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2346 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2348 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2349 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2350 checkConnectivityFullyDefined();
2351 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2352 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2358 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2359 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2360 DataArrayInt *idsOtherInConsti=0;
2361 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2364 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2366 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2367 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2370 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2371 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2373 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2374 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2375 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2376 neighThisPartAuto=0;
2377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2378 const int li[2]={0,1};
2379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2380 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2384 cellIdsRk0=s0arr.retn();
2385 cellIdsRk1=s_renum1.retn();
2389 * 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
2390 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2392 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2394 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2397 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2402 revDesc=0; desc=0; descIndx=0;
2403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2405 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2409 * Finds nodes lying on the boundary of \a this mesh.
2410 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2411 * nodes. The caller is to delete this array using decrRef() as it is no
2413 * \throw If the coordinates array is not set.
2414 * \throw If the nodal connectivity of cells is node defined.
2416 * \if ENABLE_EXAMPLES
2417 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2418 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2421 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2423 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2424 return skin->computeFetchedNodeIds();
2427 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2430 return const_cast<MEDCouplingUMesh *>(this);
2434 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2435 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2436 * 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.
2437 * 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.
2438 * 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.
2440 * \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
2441 * parameter is altered during the call.
2442 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2443 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2444 * \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.
2446 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2448 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2449 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2451 checkFullyDefined();
2452 otherDimM1OnSameCoords.checkFullyDefined();
2453 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2455 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2456 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2457 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2458 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2461 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2462 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2466 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2468 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2470 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2471 DataArrayInt *idsTmp=0;
2472 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2475 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2476 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2477 DataArrayInt *tmp0=0,*tmp1=0;
2478 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2481 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2482 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2483 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2484 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2486 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2487 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2488 nodeIdsToDuplicate=s3.retn();
2492 * This method operates a modification of the connectivity and coords in \b this.
2493 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2494 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2495 * 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
2496 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2497 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2499 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2501 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2502 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2504 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2506 int nbOfNodes=getNumberOfNodes();
2507 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2508 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2512 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2513 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2515 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2517 * \sa renumberNodesInConn
2519 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2521 checkConnectivityFullyDefined();
2522 int *conn(getNodalConnectivity()->getPointer());
2523 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2524 int nbOfCells(getNumberOfCells());
2525 for(int i=0;i<nbOfCells;i++)
2526 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2528 int& node=conn[iconn];
2529 if(node>=0)//avoid polyhedron separator
2534 _nodal_connec->declareAsNew();
2539 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2540 * 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
2543 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2545 checkConnectivityFullyDefined();
2546 int *conn(getNodalConnectivity()->getPointer());
2547 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2548 int nbOfCells(getNumberOfCells());
2549 for(int i=0;i<nbOfCells;i++)
2550 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2552 int& node=conn[iconn];
2553 if(node>=0)//avoid polyhedron separator
2555 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2556 if(it!=newNodeNumbersO2N.end())
2562 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2563 throw INTERP_KERNEL::Exception(oss.str().c_str());
2567 _nodal_connec->declareAsNew();
2572 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2573 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2574 * This method is a generalization of shiftNodeNumbersInConn().
2575 * \warning This method performs no check of validity of new ids. **Use it with care !**
2576 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2577 * this->getNumberOfNodes(), in "Old to New" mode.
2578 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2579 * \throw If the nodal connectivity of cells is not defined.
2581 * \if ENABLE_EXAMPLES
2582 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2583 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2586 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2588 checkConnectivityFullyDefined();
2589 int *conn=getNodalConnectivity()->getPointer();
2590 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2591 int nbOfCells(getNumberOfCells());
2592 for(int i=0;i<nbOfCells;i++)
2593 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2595 int& node=conn[iconn];
2596 if(node>=0)//avoid polyhedron separator
2598 node=newNodeNumbersO2N[node];
2601 _nodal_connec->declareAsNew();
2606 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2607 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2608 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2610 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2612 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2614 checkConnectivityFullyDefined();
2615 int *conn=getNodalConnectivity()->getPointer();
2616 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2617 int nbOfCells=getNumberOfCells();
2618 for(int i=0;i<nbOfCells;i++)
2619 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2621 int& node=conn[iconn];
2622 if(node>=0)//avoid polyhedron separator
2627 _nodal_connec->declareAsNew();
2632 * This method operates a modification of the connectivity in \b this.
2633 * 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.
2634 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2635 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2636 * 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
2637 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2638 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2640 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2641 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2643 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2644 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2645 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2647 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2649 checkConnectivityFullyDefined();
2650 std::map<int,int> m;
2652 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2654 int *conn=getNodalConnectivity()->getPointer();
2655 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2656 int nbOfCells=getNumberOfCells();
2657 for(int i=0;i<nbOfCells;i++)
2658 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2660 int& node=conn[iconn];
2661 if(node>=0)//avoid polyhedron separator
2663 std::map<int,int>::iterator it=m.find(node);
2672 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2674 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2675 * After the call of this method the number of cells remains the same as before.
2677 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2678 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2679 * be strictly in [0;this->getNumberOfCells()).
2681 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2682 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2683 * should be contained in[0;this->getNumberOfCells()).
2685 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2687 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2689 checkConnectivityFullyDefined();
2690 int nbCells=getNumberOfCells();
2691 const int *array=old2NewBg;
2693 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2695 const int *conn=_nodal_connec->getConstPointer();
2696 const int *connI=_nodal_connec_index->getConstPointer();
2697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2698 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2699 const int *n2oPtr=n2o->begin();
2700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2701 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2702 newConn->copyStringInfoFrom(*_nodal_connec);
2703 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2704 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2705 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2707 int *newC=newConn->getPointer();
2708 int *newCI=newConnI->getPointer();
2711 for(int i=0;i<nbCells;i++)
2714 int nbOfElts=connI[pos+1]-connI[pos];
2715 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2720 setConnectivity(newConn,newConnI);
2722 free(const_cast<int *>(array));
2726 * Finds cells whose bounding boxes intersect a given bounding box.
2727 * \param [in] bbox - an array defining the bounding box via coordinates of its
2728 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2730 * \param [in] eps - a factor used to increase size of the bounding box of cell
2731 * before comparing it with \a bbox. This factor is multiplied by the maximal
2732 * extent of the bounding box of cell to produce an addition to this bounding box.
2733 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2734 * cells. The caller is to delete this array using decrRef() as it is no more
2736 * \throw If the coordinates array is not set.
2737 * \throw If the nodal connectivity of cells is not defined.
2739 * \if ENABLE_EXAMPLES
2740 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2741 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2744 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2746 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2747 if(getMeshDimension()==-1)
2749 elems->pushBackSilent(0);
2750 return elems.retn();
2752 int dim=getSpaceDimension();
2753 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2754 const int* conn = getNodalConnectivity()->getConstPointer();
2755 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2756 const double* coords = getCoords()->getConstPointer();
2757 int nbOfCells=getNumberOfCells();
2758 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2760 for (int i=0; i<dim; i++)
2762 elem_bb[i*2]=std::numeric_limits<double>::max();
2763 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2766 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2768 int node= conn[inode];
2769 if(node>=0)//avoid polyhedron separator
2771 for (int idim=0; idim<dim; idim++)
2773 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2775 elem_bb[idim*2] = coords[node*dim+idim] ;
2777 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2779 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2784 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2785 elems->pushBackSilent(ielem);
2787 return elems.retn();
2791 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2792 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2793 * added in 'elems' parameter.
2795 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2798 if(getMeshDimension()==-1)
2800 elems->pushBackSilent(0);
2801 return elems.retn();
2803 int dim=getSpaceDimension();
2804 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2805 const int* conn = getNodalConnectivity()->getConstPointer();
2806 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2807 const double* coords = getCoords()->getConstPointer();
2808 int nbOfCells=getNumberOfCells();
2809 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2811 for (int i=0; i<dim; i++)
2813 elem_bb[i*2]=std::numeric_limits<double>::max();
2814 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2817 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2819 int node= conn[inode];
2820 if(node>=0)//avoid polyhedron separator
2822 for (int idim=0; idim<dim; idim++)
2824 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2826 elem_bb[idim*2] = coords[node*dim+idim] ;
2828 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2830 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2835 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2836 elems->pushBackSilent(ielem);
2838 return elems.retn();
2842 * Returns a type of a cell by its id.
2843 * \param [in] cellId - the id of the cell of interest.
2844 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2845 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2847 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2849 const int *ptI=_nodal_connec_index->getConstPointer();
2850 const int *pt=_nodal_connec->getConstPointer();
2851 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2852 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2855 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2856 throw INTERP_KERNEL::Exception(oss.str().c_str());
2861 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2862 * This method does not throw exception if geometric type \a type is not in \a this.
2863 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2864 * The coordinates array is not considered here.
2866 * \param [in] type the geometric type
2867 * \return cell ids in this having geometric type \a type.
2869 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2872 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2874 checkConnectivityFullyDefined();
2875 int nbCells=getNumberOfCells();
2876 int mdim=getMeshDimension();
2877 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2878 if(mdim!=(int)cm.getDimension())
2879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2880 const int *ptI=_nodal_connec_index->getConstPointer();
2881 const int *pt=_nodal_connec->getConstPointer();
2882 for(int i=0;i<nbCells;i++)
2884 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2885 ret->pushBackSilent(i);
2891 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2893 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2895 const int *ptI=_nodal_connec_index->getConstPointer();
2896 const int *pt=_nodal_connec->getConstPointer();
2897 int nbOfCells=getNumberOfCells();
2899 for(int i=0;i<nbOfCells;i++)
2900 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2906 * Returns the nodal connectivity of a given cell.
2907 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2908 * all returned node ids can be used in getCoordinatesOfNode().
2909 * \param [in] cellId - an id of the cell of interest.
2910 * \param [in,out] conn - a vector where the node ids are appended. It is not
2911 * cleared before the appending.
2912 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2914 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2916 const int *ptI=_nodal_connec_index->getConstPointer();
2917 const int *pt=_nodal_connec->getConstPointer();
2918 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2923 std::string MEDCouplingUMesh::simpleRepr() const
2925 static const char msg0[]="No coordinates specified !";
2926 std::ostringstream ret;
2927 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2928 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2930 double tt=getTime(tmpp1,tmpp2);
2931 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2932 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2934 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2936 { ret << " Mesh dimension has not been set or is invalid !"; }
2939 const int spaceDim=getSpaceDimension();
2940 ret << spaceDim << "\nInfo attached on space dimension : ";
2941 for(int i=0;i<spaceDim;i++)
2942 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2946 ret << msg0 << "\n";
2947 ret << "Number of nodes : ";
2949 ret << getNumberOfNodes() << "\n";
2951 ret << msg0 << "\n";
2952 ret << "Number of cells : ";
2953 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2954 ret << getNumberOfCells() << "\n";
2956 ret << "No connectivity specified !" << "\n";
2957 ret << "Cell types present : ";
2958 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2960 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2961 ret << cm.getRepr() << " ";
2967 std::string MEDCouplingUMesh::advancedRepr() const
2969 std::ostringstream ret;
2970 ret << simpleRepr();
2971 ret << "\nCoordinates array : \n___________________\n\n";
2973 _coords->reprWithoutNameStream(ret);
2975 ret << "No array set !\n";
2976 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2977 reprConnectivityOfThisLL(ret);
2982 * This method returns a C++ code that is a dump of \a this.
2983 * This method will throw if this is not fully defined.
2985 std::string MEDCouplingUMesh::cppRepr() const
2987 static const char coordsName[]="coords";
2988 static const char connName[]="conn";
2989 static const char connIName[]="connI";
2990 checkFullyDefined();
2991 std::ostringstream ret; ret << "// coordinates" << std::endl;
2992 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2993 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2994 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2995 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2996 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2997 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2998 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3002 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3004 std::ostringstream ret;
3005 reprConnectivityOfThisLL(ret);
3010 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3011 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3012 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3015 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3016 * 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
3017 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3019 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3021 int mdim=getMeshDimension();
3023 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3024 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3026 bool needToCpyCT=true;
3029 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3037 if(!_nodal_connec_index)
3039 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3044 tmp2=_nodal_connec_index;
3047 ret->setConnectivity(tmp1,tmp2,false);
3052 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3053 ret->setCoords(coords);
3056 ret->setCoords(_coords);
3060 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3062 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3064 int nbOfCells=getNumberOfCells();
3065 const int *c=_nodal_connec->getConstPointer();
3066 const int *ci=_nodal_connec_index->getConstPointer();
3067 for(int i=0;i<nbOfCells;i++)
3069 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3070 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3071 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3076 stream << "Connectivity not defined !\n";
3079 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3081 const int *ptI=_nodal_connec_index->getConstPointer();
3082 const int *pt=_nodal_connec->getConstPointer();
3083 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3084 return ptI[cellId+1]-ptI[cellId]-1;
3086 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3090 * Returns types of cells of the specified part of \a this mesh.
3091 * This method avoids computing sub-mesh explicitely to get its types.
3092 * \param [in] begin - an array of cell ids of interest.
3093 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3094 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3095 * describing the cell types.
3096 * \throw If the coordinates array is not set.
3097 * \throw If the nodal connectivity of cells is not defined.
3098 * \sa getAllGeoTypes()
3100 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3102 checkFullyDefined();
3103 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3104 const int *conn=_nodal_connec->getConstPointer();
3105 const int *connIndex=_nodal_connec_index->getConstPointer();
3106 for(const int *w=begin;w!=end;w++)
3107 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3112 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3113 * a set of types of cells constituting \a this mesh.
3114 * This method is for advanced users having prepared their connectivity before. For
3115 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3116 * \param [in] conn - the nodal connectivity array.
3117 * \param [in] connIndex - the nodal connectivity index array.
3118 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3121 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3123 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3124 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3125 if(isComputingTypes)
3131 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3132 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3134 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3135 _nodal_connec(0),_nodal_connec_index(0),
3136 _types(other._types)
3138 if(other._nodal_connec)
3139 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3140 if(other._nodal_connec_index)
3141 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3144 MEDCouplingUMesh::~MEDCouplingUMesh()
3147 _nodal_connec->decrRef();
3148 if(_nodal_connec_index)
3149 _nodal_connec_index->decrRef();
3153 * Recomputes a set of cell types of \a this mesh. For more info see
3154 * \ref MEDCouplingUMeshNodalConnectivity.
3156 void MEDCouplingUMesh::computeTypes()
3158 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3162 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3164 void MEDCouplingUMesh::checkFullyDefined() const
3166 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3167 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3171 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3173 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3175 if(!_nodal_connec_index || !_nodal_connec)
3176 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3180 * Returns a number of cells constituting \a this mesh.
3181 * \return int - the number of cells in \a this mesh.
3182 * \throw If the nodal connectivity of cells is not defined.
3184 int MEDCouplingUMesh::getNumberOfCells() const
3186 if(_nodal_connec_index)
3187 return _nodal_connec_index->getNumberOfTuples()-1;
3192 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3196 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3197 * mesh. For more info see \ref MEDCouplingMeshesPage.
3198 * \return int - the dimension of \a this mesh.
3199 * \throw If the mesh dimension is not defined using setMeshDimension().
3201 int MEDCouplingUMesh::getMeshDimension() const
3204 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3209 * Returns a length of the nodal connectivity array.
3210 * This method is for test reason. Normally the integer returned is not useable by
3211 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3212 * \return int - the length of the nodal connectivity array.
3214 int MEDCouplingUMesh::getMeshLength() const
3216 return _nodal_connec->getNbOfElems();
3220 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3222 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3224 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3225 tinyInfo.push_back(getMeshDimension());
3226 tinyInfo.push_back(getNumberOfCells());
3228 tinyInfo.push_back(getMeshLength());
3230 tinyInfo.push_back(-1);
3234 * First step of unserialization process.
3236 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3238 return tinyInfo[6]<=0;
3242 * Second step of serialization process.
3243 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3245 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3247 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3249 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3253 * Third and final step of serialization process.
3255 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3257 MEDCouplingPointSet::serialize(a1,a2);
3258 if(getMeshDimension()>-1)
3260 a1=DataArrayInt::New();
3261 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3262 int *ptA1=a1->getPointer();
3263 const int *conn=getNodalConnectivity()->getConstPointer();
3264 const int *index=getNodalConnectivityIndex()->getConstPointer();
3265 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3266 std::copy(conn,conn+getMeshLength(),ptA1);
3273 * Second and final unserialization process.
3274 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3276 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3278 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3279 setMeshDimension(tinyInfo[5]);
3283 const int *recvBuffer=a1->getConstPointer();
3284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3285 myConnecIndex->alloc(tinyInfo[6]+1,1);
3286 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3288 myConnec->alloc(tinyInfo[7],1);
3289 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3290 setConnectivity(myConnec, myConnecIndex);
3295 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3296 * CellIds are given using range specified by a start an end and step.
3298 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3300 checkFullyDefined();
3301 int ncell=getNumberOfCells();
3302 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3303 ret->_mesh_dim=_mesh_dim;
3304 ret->setCoords(_coords);
3305 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3307 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3309 const int *conn=_nodal_connec->getConstPointer();
3310 const int *connIndex=_nodal_connec_index->getConstPointer();
3311 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3313 if(work>=0 && work<ncell)
3315 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3319 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3320 throw INTERP_KERNEL::Exception(oss.str().c_str());
3323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3324 int *newConnPtr=newConn->getPointer();
3325 std::set<INTERP_KERNEL::NormalizedCellType> types;
3327 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3329 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3330 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3332 ret->setConnectivity(newConn,newConnI,false);
3334 ret->copyTinyInfoFrom(this);
3339 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3340 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3341 * The return newly allocated mesh will share the same coordinates as \a this.
3343 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3345 checkConnectivityFullyDefined();
3346 int ncell=getNumberOfCells();
3347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3348 ret->_mesh_dim=_mesh_dim;
3349 ret->setCoords(_coords);
3350 std::size_t nbOfElemsRet=std::distance(begin,end);
3351 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3353 const int *conn=_nodal_connec->getConstPointer();
3354 const int *connIndex=_nodal_connec_index->getConstPointer();
3356 for(const int *work=begin;work!=end;work++,newNbring++)
3358 if(*work>=0 && *work<ncell)
3359 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3363 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3364 throw INTERP_KERNEL::Exception(oss.str().c_str());
3367 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3368 int *connRetWork=connRet;
3369 std::set<INTERP_KERNEL::NormalizedCellType> types;
3370 for(const int *work=begin;work!=end;work++)
3372 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3373 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3376 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3378 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3379 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3381 ret->copyTinyInfoFrom(this);
3386 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3388 * For 1D cells, the returned field contains lengths.<br>
3389 * For 2D cells, the returned field contains areas.<br>
3390 * For 3D cells, the returned field contains volumes.
3391 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3392 * orientation, i.e. the volume is always positive.
3393 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3394 * and one time . The caller is to delete this field using decrRef() as it is no
3397 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3399 std::string name="MeasureOfMesh_";
3401 int nbelem=getNumberOfCells();
3402 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3403 field->setName(name);
3404 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3405 array->alloc(nbelem,1);
3406 double *area_vol=array->getPointer();
3407 field->setArray(array) ; array=0;
3408 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3409 field->synchronizeTimeWithMesh();
3410 if(getMeshDimension()!=-1)
3413 INTERP_KERNEL::NormalizedCellType type;
3414 int dim_space=getSpaceDimension();
3415 const double *coords=getCoords()->getConstPointer();
3416 const int *connec=getNodalConnectivity()->getConstPointer();
3417 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3418 for(int iel=0;iel<nbelem;iel++)
3420 ipt=connec_index[iel];
3421 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3422 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);
3425 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3429 area_vol[0]=std::numeric_limits<double>::max();
3431 return field.retn();
3435 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3437 * For 1D cells, the returned array contains lengths.<br>
3438 * For 2D cells, the returned array contains areas.<br>
3439 * For 3D cells, the returned array contains volumes.
3440 * This method avoids building explicitly a part of \a this mesh to perform the work.
3441 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3442 * orientation, i.e. the volume is always positive.
3443 * \param [in] begin - an array of cell ids of interest.
3444 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3445 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3446 * delete this array using decrRef() as it is no more needed.
3448 * \if ENABLE_EXAMPLES
3449 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3450 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3452 * \sa getMeasureField()
3454 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3456 std::string name="PartMeasureOfMesh_";
3458 int nbelem=(int)std::distance(begin,end);
3459 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3460 array->setName(name);
3461 array->alloc(nbelem,1);
3462 double *area_vol=array->getPointer();
3463 if(getMeshDimension()!=-1)
3466 INTERP_KERNEL::NormalizedCellType type;
3467 int dim_space=getSpaceDimension();
3468 const double *coords=getCoords()->getConstPointer();
3469 const int *connec=getNodalConnectivity()->getConstPointer();
3470 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3471 for(const int *iel=begin;iel!=end;iel++)
3473 ipt=connec_index[*iel];
3474 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3475 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3478 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3482 area_vol[0]=std::numeric_limits<double>::max();
3484 return array.retn();
3488 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3489 * \a this one. The returned field contains the dual cell volume for each corresponding
3490 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3491 * the dual mesh in P1 sens of \a this.<br>
3492 * For 1D cells, the returned field contains lengths.<br>
3493 * For 2D cells, the returned field contains areas.<br>
3494 * For 3D cells, the returned field contains volumes.
3495 * This method is useful to check "P1*" conservative interpolators.
3496 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3497 * orientation, i.e. the volume is always positive.
3498 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499 * nodes and one time. The caller is to delete this array using decrRef() as
3500 * it is no more needed.
3502 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3504 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3505 std::string name="MeasureOnNodeOfMesh_";
3507 int nbNodes=getNumberOfNodes();
3508 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3509 double cst=1./((double)getMeshDimension()+1.);
3510 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3511 array->alloc(nbNodes,1);
3512 double *valsToFill=array->getPointer();
3513 std::fill(valsToFill,valsToFill+nbNodes,0.);
3514 const double *values=tmp->getArray()->getConstPointer();
3515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3516 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3517 getReverseNodalConnectivity(da,daInd);
3518 const int *daPtr=da->getConstPointer();
3519 const int *daIPtr=daInd->getConstPointer();
3520 for(int i=0;i<nbNodes;i++)
3521 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3522 valsToFill[i]+=cst*values[*cell];
3524 ret->setArray(array);
3529 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3530 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3531 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3532 * and are normalized.
3533 * <br> \a this can be either
3534 * - a 2D mesh in 2D or 3D space or
3535 * - an 1D mesh in 2D space.
3537 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3538 * cells and one time. The caller is to delete this field using decrRef() as
3539 * it is no more needed.
3540 * \throw If the nodal connectivity of cells is not defined.
3541 * \throw If the coordinates array is not set.
3542 * \throw If the mesh dimension is not set.
3543 * \throw If the mesh and space dimension is not as specified above.
3545 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3547 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3548 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3549 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3550 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3551 int nbOfCells=getNumberOfCells();
3552 int nbComp=getMeshDimension()+1;
3553 array->alloc(nbOfCells,nbComp);
3554 double *vals=array->getPointer();
3555 const int *connI=_nodal_connec_index->getConstPointer();
3556 const int *conn=_nodal_connec->getConstPointer();
3557 const double *coords=_coords->getConstPointer();
3558 if(getMeshDimension()==2)
3560 if(getSpaceDimension()==3)
3562 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3563 const double *locPtr=loc->getConstPointer();
3564 for(int i=0;i<nbOfCells;i++,vals+=3)
3566 int offset=connI[i];
3567 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3568 double n=INTERP_KERNEL::norm<3>(vals);
3569 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3574 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3575 const double *isAbsPtr=isAbs->getArray()->begin();
3576 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3577 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3580 else//meshdimension==1
3583 for(int i=0;i<nbOfCells;i++)
3585 int offset=connI[i];
3586 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3587 double n=INTERP_KERNEL::norm<2>(tmp);
3588 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3593 ret->setArray(array);
3595 ret->synchronizeTimeWithSupport();
3600 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3601 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3602 * and are normalized.
3603 * <br> \a this can be either
3604 * - a 2D mesh in 2D or 3D space or
3605 * - an 1D mesh in 2D space.
3607 * This method avoids building explicitly a part of \a this mesh to perform the work.
3608 * \param [in] begin - an array of cell ids of interest.
3609 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3610 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3611 * cells and one time. The caller is to delete this field using decrRef() as
3612 * it is no more needed.
3613 * \throw If the nodal connectivity of cells is not defined.
3614 * \throw If the coordinates array is not set.
3615 * \throw If the mesh dimension is not set.
3616 * \throw If the mesh and space dimension is not as specified above.
3617 * \sa buildOrthogonalField()
3619 * \if ENABLE_EXAMPLES
3620 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3621 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3624 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3626 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3627 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3628 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3629 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3630 std::size_t nbelems=std::distance(begin,end);
3631 int nbComp=getMeshDimension()+1;
3632 array->alloc((int)nbelems,nbComp);
3633 double *vals=array->getPointer();
3634 const int *connI=_nodal_connec_index->getConstPointer();
3635 const int *conn=_nodal_connec->getConstPointer();
3636 const double *coords=_coords->getConstPointer();
3637 if(getMeshDimension()==2)
3639 if(getSpaceDimension()==3)
3641 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3642 const double *locPtr=loc->getConstPointer();
3643 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3645 int offset=connI[*i];
3646 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3647 double n=INTERP_KERNEL::norm<3>(vals);
3648 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3653 for(std::size_t i=0;i<nbelems;i++)
3654 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3657 else//meshdimension==1
3660 for(const int *i=begin;i!=end;i++)
3662 int offset=connI[*i];
3663 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3664 double n=INTERP_KERNEL::norm<2>(tmp);
3665 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3670 ret->setArray(array);
3672 ret->synchronizeTimeWithSupport();
3677 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3678 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3679 * and are \b not normalized.
3680 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3681 * cells and one time. The caller is to delete this field using decrRef() as
3682 * it is no more needed.
3683 * \throw If the nodal connectivity of cells is not defined.
3684 * \throw If the coordinates array is not set.
3685 * \throw If \a this->getMeshDimension() != 1.
3686 * \throw If \a this mesh includes cells of type other than SEG2.
3688 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3690 if(getMeshDimension()!=1)
3691 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3692 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3693 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3694 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3695 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3696 int nbOfCells=getNumberOfCells();
3697 int spaceDim=getSpaceDimension();
3698 array->alloc(nbOfCells,spaceDim);
3699 double *pt=array->getPointer();
3700 const double *coo=getCoords()->getConstPointer();
3701 std::vector<int> conn;
3703 for(int i=0;i<nbOfCells;i++)
3706 getNodeIdsOfCell(i,conn);
3707 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3709 ret->setArray(array);
3711 ret->synchronizeTimeWithSupport();
3716 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3717 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3718 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3719 * from. If a result face is shared by two 3D cells, then the face in included twice in
3721 * \param [in] origin - 3 components of a point defining location of the plane.
3722 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3723 * must be greater than 1e-6.
3724 * \param [in] eps - half-thickness of the plane.
3725 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3726 * producing correspondent 2D cells. The caller is to delete this array
3727 * using decrRef() as it is no more needed.
3728 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3729 * not share the node coordinates array with \a this mesh. The caller is to
3730 * delete this mesh using decrRef() as it is no more needed.
3731 * \throw If the coordinates array is not set.
3732 * \throw If the nodal connectivity of cells is not defined.
3733 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3734 * \throw If magnitude of \a vec is less than 1e-6.
3735 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3736 * \throw If \a this includes quadratic cells.
3738 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3740 checkFullyDefined();
3741 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3742 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3744 if(candidates->empty())
3745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3746 std::vector<int> nodes;
3747 DataArrayInt *cellIds1D=0;
3748 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3749 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3755 revDesc2=0; revDescIndx2=0;
3756 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3757 revDesc1=0; revDescIndx1=0;
3758 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3761 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3762 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3764 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3765 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3766 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3767 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3768 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3769 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3770 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3771 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3772 if(cellIds2->empty())
3773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3774 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3775 ret->setCoords(mDesc1->getCoords());
3776 ret->setConnectivity(conn,connI,true);
3777 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3782 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3783 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
3784 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3786 * \param [in] origin - 3 components of a point defining location of the plane.
3787 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3788 * must be greater than 1e-6.
3789 * \param [in] eps - half-thickness of the plane.
3790 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3791 * producing correspondent segments. The caller is to delete this array
3792 * using decrRef() as it is no more needed.
3793 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3794 * mesh in 3D space. This mesh does not share the node coordinates array with
3795 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3797 * \throw If the coordinates array is not set.
3798 * \throw If the nodal connectivity of cells is not defined.
3799 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3800 * \throw If magnitude of \a vec is less than 1e-6.
3801 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3802 * \throw If \a this includes quadratic cells.
3804 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3806 checkFullyDefined();
3807 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3808 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3810 if(candidates->empty())
3811 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3812 std::vector<int> nodes;
3813 DataArrayInt *cellIds1D=0;
3814 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3815 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3820 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3821 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3824 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3825 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3827 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3828 int ncellsSub=subMesh->getNumberOfCells();
3829 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3830 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3831 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3832 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3835 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3836 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3837 for(int i=0;i<ncellsSub;i++)
3839 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3841 if(cut3DSurf[i].first!=-2)
3843 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3844 connI->pushBackSilent(conn->getNumberOfTuples());
3845 cellIds2->pushBackSilent(i);
3849 int cellId3DSurf=cut3DSurf[i].second;
3850 int offset=nodalI[cellId3DSurf]+1;
3851 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3852 for(int j=0;j<nbOfEdges;j++)
3854 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3855 connI->pushBackSilent(conn->getNumberOfTuples());
3856 cellIds2->pushBackSilent(cellId3DSurf);
3861 if(cellIds2->empty())
3862 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3863 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3864 ret->setCoords(mDesc1->getCoords());
3865 ret->setConnectivity(conn,connI,true);
3866 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3871 * Finds cells whose bounding boxes intersect a given plane.
3872 * \param [in] origin - 3 components of a point defining location of the plane.
3873 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3874 * must be greater than 1e-6.
3875 * \param [in] eps - half-thickness of the plane.
3876 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3877 * cells. The caller is to delete this array using decrRef() as it is no more
3879 * \throw If the coordinates array is not set.
3880 * \throw If the nodal connectivity of cells is not defined.
3881 * \throw If \a this->getSpaceDimension() != 3.
3882 * \throw If magnitude of \a vec is less than 1e-6.
3883 * \sa buildSlice3D()
3885 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3887 checkFullyDefined();
3888 if(getSpaceDimension()!=3)
3889 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3890 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3892 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3894 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3895 double angle=acos(vec[2]/normm);
3896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3900 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3901 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3902 if(normm2/normm>1e-6)
3903 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3904 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3906 mw->getBoundingBox(bbox);
3907 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3908 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3912 getBoundingBox(bbox);
3913 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3914 cellIds=getCellsInBoundingBox(bbox,eps);
3916 return cellIds.retn();
3920 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3921 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3922 * No consideration of coordinate is done by this method.
3923 * 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)
3924 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3926 bool MEDCouplingUMesh::isContiguous1D() const
3928 if(getMeshDimension()!=1)
3929 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3930 int nbCells=getNumberOfCells();
3932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3933 const int *connI=_nodal_connec_index->getConstPointer();
3934 const int *conn=_nodal_connec->getConstPointer();
3935 int ref=conn[connI[0]+2];
3936 for(int i=1;i<nbCells;i++)
3938 if(conn[connI[i]+1]!=ref)
3940 ref=conn[connI[i]+2];
3946 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3947 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3948 * \param pt reference point of the line
3949 * \param v normalized director vector of the line
3950 * \param eps max precision before throwing an exception
3951 * \param res output of size this->getNumberOfCells
3953 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3955 if(getMeshDimension()!=1)
3956 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3957 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3958 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3959 if(getSpaceDimension()!=3)
3960 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3961 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3962 const double *fPtr=f->getArray()->getConstPointer();
3964 for(int i=0;i<getNumberOfCells();i++)
3966 const double *tmp1=fPtr+3*i;
3967 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3968 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3969 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3970 double n1=INTERP_KERNEL::norm<3>(tmp);
3971 n1/=INTERP_KERNEL::norm<3>(tmp1);
3973 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3975 const double *coo=getCoords()->getConstPointer();
3976 for(int i=0;i<getNumberOfNodes();i++)
3978 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3979 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3980 res[i]=std::accumulate(tmp,tmp+3,0.);
3985 * 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.
3986 * \a this is expected to be a mesh so that its space dimension is equal to its
3987 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3988 * 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).
3990 * 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
3991 * 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).
3992 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3994 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3995 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3997 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3998 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3999 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4000 * \return the positive value of the distance.
4001 * \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
4003 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4005 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4007 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4008 if(meshDim!=spaceDim-1)
4009 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4010 if(meshDim!=2 && meshDim!=1)
4011 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4012 checkFullyDefined();
4013 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4014 { 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()); }
4015 DataArrayInt *ret1=0;
4016 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4017 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4019 cellId=*ret1Safe->begin();
4020 return *ret0->begin();
4024 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4025 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4026 * 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
4027 * 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).
4028 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4030 * \a this is expected to be a mesh so that its space dimension is equal to its
4031 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4032 * 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).
4034 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4035 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4037 * \param [in] pts the list of points in which each tuple represents a point
4038 * \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.
4039 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4040 * \throw if number of components of \a pts is not equal to the space dimension.
4041 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4042 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4044 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4047 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4048 pts->checkAllocated();
4049 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4050 if(meshDim!=spaceDim-1)
4051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4052 if(meshDim!=2 && meshDim!=1)
4053 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4054 if(pts->getNumberOfComponents()!=spaceDim)
4056 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4057 throw INTERP_KERNEL::Exception(oss.str().c_str());
4059 checkFullyDefined();
4060 int nbCells=getNumberOfCells();
4062 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4063 int nbOfPts=pts->getNumberOfTuples();
4064 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4066 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4067 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4068 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4069 const double *bbox(bboxArr->begin());
4074 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4075 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4077 double x=std::numeric_limits<double>::max();
4078 std::vector<int> elems;
4079 myTree.getMinDistanceOfMax(ptsPtr,x);
4080 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4081 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4087 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4088 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4090 double x=std::numeric_limits<double>::max();
4091 std::vector<int> elems;
4092 myTree.getMinDistanceOfMax(ptsPtr,x);
4093 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4094 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4099 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4101 cellIds=ret1.retn();
4106 * \param [in] pt the start pointer (included) of the coordinates of the point
4107 * \param [in] cellIdsBg the start pointer (included) of cellIds
4108 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4109 * \param [in] nc nodal connectivity
4110 * \param [in] ncI nodal connectivity index
4111 * \param [in,out] ret0 the min distance between \a this and the external input point
4112 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4113 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4115 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)
4118 ret0=std::numeric_limits<double>::max();
4119 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4121 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4123 case INTERP_KERNEL::NORM_TRI3:
4125 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4127 { ret0=tmp; cellId=*zeCell; }
4130 case INTERP_KERNEL::NORM_QUAD4:
4131 case INTERP_KERNEL::NORM_POLYGON:
4133 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4135 { ret0=tmp; cellId=*zeCell; }
4139 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4145 * \param [in] pt the start pointer (included) of the coordinates of the point
4146 * \param [in] cellIdsBg the start pointer (included) of cellIds
4147 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4148 * \param [in] nc nodal connectivity
4149 * \param [in] ncI nodal connectivity index
4150 * \param [in,out] ret0 the min distance between \a this and the external input point
4151 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4152 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4154 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)
4157 ret0=std::numeric_limits<double>::max();
4158 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4160 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4162 case INTERP_KERNEL::NORM_SEG2:
4164 std::size_t uselessEntry=0;
4165 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4168 { ret0=tmp; cellId=*zeCell; }
4172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4178 * Finds cells in contact with a ball (i.e. a point with precision).
4179 * 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.
4180 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4182 * \warning This method is suitable if the caller intends to evaluate only one
4183 * point, for more points getCellsContainingPoints() is recommended as it is
4185 * \param [in] pos - array of coordinates of the ball central point.
4186 * \param [in] eps - ball radius.
4187 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4188 * if there are no such cells.
4189 * \throw If the coordinates array is not set.
4190 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4192 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4194 std::vector<int> elts;
4195 getCellsContainingPoint(pos,eps,elts);
4198 return elts.front();
4202 * Finds cells in contact with a ball (i.e. a point with precision).
4203 * 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.
4204 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4205 * \warning This method is suitable if the caller intends to evaluate only one
4206 * point, for more points getCellsContainingPoints() is recommended as it is
4208 * \param [in] pos - array of coordinates of the ball central point.
4209 * \param [in] eps - ball radius.
4210 * \param [out] elts - vector returning ids of the found cells. It is cleared
4211 * before inserting ids.
4212 * \throw If the coordinates array is not set.
4213 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4215 * \if ENABLE_EXAMPLES
4216 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4217 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4220 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4223 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4224 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4229 namespace ParaMEDMEM
4231 template<const int SPACEDIMM>
4235 static const int MY_SPACEDIM=SPACEDIMM;
4236 static const int MY_MESHDIM=8;
4237 typedef int MyConnType;
4238 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4240 // useless, but for windows compilation ...
4241 const double* getCoordinatesPtr() const { return 0; }
4242 const int* getConnectivityPtr() const { return 0; }
4243 const int* getConnectivityIndexPtr() const { return 0; }
4244 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4248 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4250 INTERP_KERNEL::Edge *ret(0);
4251 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]));
4252 m[n0]=bg[0]; m[n1]=bg[1];
4255 case INTERP_KERNEL::NORM_SEG2:
4257 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4260 case INTERP_KERNEL::NORM_SEG3:
4262 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4263 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4264 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4265 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4266 bool colinearity(inters.areColinears());
4267 delete e1; delete e2;
4269 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4271 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4275 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4280 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4282 INTERP_KERNEL::Edge *ret=0;
4285 case INTERP_KERNEL::NORM_SEG2:
4287 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4290 case INTERP_KERNEL::NORM_SEG3:
4292 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4293 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4294 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4295 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4296 bool colinearity=inters.areColinears();
4297 delete e1; delete e2;
4299 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4301 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4302 mapp2[bg[2]].second=false;
4306 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4312 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4313 * the global mesh 'mDesc'.
4314 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4315 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4317 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4318 std::map<INTERP_KERNEL::Node *,int>& mapp)
4321 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.
4322 const double *coo=mDesc->getCoords()->getConstPointer();
4323 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4324 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4326 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4327 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4328 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4330 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4331 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4333 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4334 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4336 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4337 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4339 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4341 if((*it2).second.second)
4342 mapp[(*it2).second.first]=(*it2).first;
4343 ((*it2).second.first)->decrRef();
4348 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4352 int locId=nodeId-offset2;
4353 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4357 int locId=nodeId-offset1;
4358 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4360 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4364 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4366 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4367 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4368 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4370 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4372 int eltId1=abs(*desc1)-1;
4373 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4375 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4376 if(it==mappRev.end())
4378 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4389 template<int SPACEDIM>
4390 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4391 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4393 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4394 int *eltsIndexPtr(eltsIndex->getPointer());
4395 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4396 const double *bbox(bboxArr->begin());
4397 int nbOfCells=getNumberOfCells();
4398 const int *conn=_nodal_connec->getConstPointer();
4399 const int *connI=_nodal_connec_index->getConstPointer();
4400 double bb[2*SPACEDIM];
4401 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4402 for(int i=0;i<nbOfPoints;i++)
4404 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4405 for(int j=0;j<SPACEDIM;j++)
4407 bb[2*j]=pos[SPACEDIM*i+j];
4408 bb[2*j+1]=pos[SPACEDIM*i+j];
4410 std::vector<int> candidates;
4411 myTree.getIntersectingElems(bb,candidates);
4412 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4414 int sz(connI[(*iter)+1]-connI[*iter]-1);
4415 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4417 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4418 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4422 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4423 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4424 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4425 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4426 INTERP_KERNEL::QuadraticPolygon *pol(0);
4427 for(int j=0;j<sz;j++)
4429 int nodeId(conn[connI[*iter]+1+j]);
4430 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4432 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4433 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4435 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4436 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4437 double a(0.),b(0.),c(0.);
4438 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4439 status=pol->isInOrOut2(n);
4440 delete pol; n->decrRef();
4444 eltsIndexPtr[i+1]++;
4445 elts->pushBackSilent(*iter);
4451 * Finds cells in contact with several balls (i.e. points with precision).
4452 * This method is an extension of getCellContainingPoint() and
4453 * getCellsContainingPoint() for the case of multiple points.
4454 * 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.
4455 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4456 * \param [in] pos - an array of coordinates of points in full interlace mode :
4457 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4458 * this->getSpaceDimension() * \a nbOfPoints
4459 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4460 * \param [in] eps - radius of balls (i.e. the precision).
4461 * \param [out] elts - vector returning ids of found cells.
4462 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4463 * dividing cell ids in \a elts into groups each referring to one
4464 * point. Its every element (except the last one) is an index pointing to the
4465 * first id of a group of cells. For example cells in contact with the *i*-th
4466 * point are described by following range of indices:
4467 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4468 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4469 * Number of cells in contact with the *i*-th point is
4470 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4471 * \throw If the coordinates array is not set.
4472 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4474 * \if ENABLE_EXAMPLES
4475 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4476 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4479 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4482 int spaceDim=getSpaceDimension();
4483 int mDim=getMeshDimension();
4488 const double *coords=_coords->getConstPointer();
4489 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4496 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4498 else if(spaceDim==2)
4502 const double *coords=_coords->getConstPointer();
4503 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4506 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4508 else if(spaceDim==1)
4512 const double *coords=_coords->getConstPointer();
4513 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4516 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4519 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4523 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4524 * least two its edges intersect each other anywhere except their extremities. An
4525 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4526 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4527 * cleared before filling in.
4528 * \param [in] eps - precision.
4529 * \throw If \a this->getMeshDimension() != 2.
4530 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4532 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4534 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4535 if(getMeshDimension()!=2)
4536 throw INTERP_KERNEL::Exception(msg);
4537 int spaceDim=getSpaceDimension();
4538 if(spaceDim!=2 && spaceDim!=3)
4539 throw INTERP_KERNEL::Exception(msg);
4540 const int *conn=_nodal_connec->getConstPointer();
4541 const int *connI=_nodal_connec_index->getConstPointer();
4542 int nbOfCells=getNumberOfCells();
4543 std::vector<double> cell2DinS2;
4544 for(int i=0;i<nbOfCells;i++)
4546 int offset=connI[i];
4547 int nbOfNodesForCell=connI[i+1]-offset-1;
4548 if(nbOfNodesForCell<=3)
4550 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4551 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4552 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4559 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4561 * 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.
4562 * 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.
4564 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4565 * This convex envelop is computed using Jarvis march algorithm.
4566 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4567 * 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)
4568 * 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.
4570 * \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.
4571 * \sa MEDCouplingUMesh::colinearize2D
4573 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4575 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4577 checkFullyDefined();
4578 const double *coords=getCoords()->getConstPointer();
4579 int nbOfCells=getNumberOfCells();
4580 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4581 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4582 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4583 int *workIndexOut=nodalConnecIndexOut->getPointer();
4585 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4586 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4587 std::set<INTERP_KERNEL::NormalizedCellType> types;
4588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4589 isChanged->alloc(0,1);
4590 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4592 int pos=nodalConnecOut->getNumberOfTuples();
4593 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4594 isChanged->pushBackSilent(i);
4595 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4596 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4598 if(isChanged->empty())
4600 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4602 return isChanged.retn();
4606 * This method is \b NOT const because it can modify \a this.
4607 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4608 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4609 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4610 * \b 1 for translation and rotation around point of 'mesh1D'.
4611 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4613 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4615 checkFullyDefined();
4616 mesh1D->checkFullyDefined();
4617 if(!mesh1D->isContiguous1D())
4618 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4619 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4620 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4621 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4622 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4623 if(mesh1D->getMeshDimension()!=1)
4624 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4626 if(isPresenceOfQuadratic())
4628 if(mesh1D->isFullyQuadratic())
4631 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4633 int oldNbOfNodes(getNumberOfNodes());
4634 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4639 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4644 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4648 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4650 setCoords(newCoords);
4651 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4657 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4658 * If it is not the case an exception will be thrown.
4659 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4660 * intersection of plane defined by ('origin','vec').
4661 * This method has one in/out parameter : 'cut3DCurve'.
4662 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4663 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4664 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4665 * This method will throw an exception if \a this contains a non linear segment.
4667 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4669 checkFullyDefined();
4670 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4672 int ncells=getNumberOfCells();
4673 int nnodes=getNumberOfNodes();
4674 double vec2[3],vec3[3],vec4[3];
4675 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4677 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4678 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4679 const int *conn=_nodal_connec->getConstPointer();
4680 const int *connI=_nodal_connec_index->getConstPointer();
4681 const double *coo=_coords->getConstPointer();
4682 std::vector<double> addCoo;
4683 for(int i=0;i<ncells;i++)
4685 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4687 if(cut3DCurve[i]==-2)
4689 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4690 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];
4691 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4692 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4693 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4695 const double *st2=coo+3*st;
4696 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4697 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]));
4698 if(pos>eps && pos<1-eps)
4700 int nNode=((int)addCoo.size())/3;
4701 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4702 addCoo.insert(addCoo.end(),vec4,vec4+3);
4703 cut3DCurve[i]=nnodes+nNode;
4709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4713 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4714 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4715 coo2->alloc(newNbOfNodes,3);
4716 double *tmp=coo2->getPointer();
4717 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4718 std::copy(addCoo.begin(),addCoo.end(),tmp);
4719 DataArrayDouble::SetArrayIn(coo2,_coords);
4724 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4725 * \param mesh1D is the input 1D mesh used for translation computation.
4726 * \return newCoords new coords filled by this method.
4728 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4730 int oldNbOfNodes=getNumberOfNodes();
4731 int nbOf1DCells=mesh1D->getNumberOfCells();
4732 int spaceDim=getSpaceDimension();
4733 DataArrayDouble *ret=DataArrayDouble::New();
4734 std::vector<bool> isQuads;
4735 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4736 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4737 double *retPtr=ret->getPointer();
4738 const double *coords=getCoords()->getConstPointer();
4739 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4741 std::vector<double> c;
4745 for(int i=0;i<nbOf1DCells;i++)
4748 mesh1D->getNodeIdsOfCell(i,v);
4750 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4751 mesh1D->getCoordinatesOfNode(v[0],c);
4752 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4753 for(int j=0;j<oldNbOfNodes;j++)
4754 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4758 mesh1D->getCoordinatesOfNode(v[1],c);
4759 mesh1D->getCoordinatesOfNode(v[0],c);
4760 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4761 for(int j=0;j<oldNbOfNodes;j++)
4762 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4765 ret->copyStringInfoFrom(*getCoords());
4770 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4771 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4772 * \return newCoords new coords filled by this method.
4774 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4776 if(mesh1D->getSpaceDimension()==2)
4777 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4778 if(mesh1D->getSpaceDimension()==3)
4779 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4780 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4784 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4785 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4786 * \return newCoords new coords filled by this method.
4788 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4791 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4792 int oldNbOfNodes=getNumberOfNodes();
4793 int nbOf1DCells=mesh1D->getNumberOfCells();
4795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4796 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4797 int nbOfLevsInVec=nbOf1DCells+1;
4798 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4799 double *retPtr=ret->getPointer();
4800 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4801 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4802 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4803 tmp->setCoords(tmp2);
4804 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4805 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4806 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4807 for(int i=1;i<nbOfLevsInVec;i++)
4809 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4810 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4811 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4812 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4813 tmp->translate(vec);
4814 double tmp3[2],radius,alpha,alpha0;
4815 const double *p0=i+1<nbOfLevsInVec?begin:third;
4816 const double *p1=i+1<nbOfLevsInVec?end:begin;
4817 const double *p2=i+1<nbOfLevsInVec?third:end;
4818 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4819 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]);
4820 double angle=acos(cosangle/(radius*radius));
4821 tmp->rotate(end,0,angle);
4822 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4828 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4829 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4830 * \return newCoords new coords filled by this method.
4832 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4835 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4836 int oldNbOfNodes=getNumberOfNodes();
4837 int nbOf1DCells=mesh1D->getNumberOfCells();
4839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4840 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4841 int nbOfLevsInVec=nbOf1DCells+1;
4842 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4843 double *retPtr=ret->getPointer();
4844 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4845 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4846 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4847 tmp->setCoords(tmp2);
4848 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4849 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4850 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4851 for(int i=1;i<nbOfLevsInVec;i++)
4853 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4854 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4855 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4856 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4857 tmp->translate(vec);
4858 double tmp3[2],radius,alpha,alpha0;
4859 const double *p0=i+1<nbOfLevsInVec?begin:third;
4860 const double *p1=i+1<nbOfLevsInVec?end:begin;
4861 const double *p2=i+1<nbOfLevsInVec?third:end;
4862 double vecPlane[3]={
4863 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4864 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4865 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4867 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4870 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4871 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4872 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4874 double c2=cos(asin(s2));
4876 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4877 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4878 {-vec2[1]*s2, vec2[0]*s2, c2}
4880 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]};
4881 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]};
4882 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]};
4883 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4884 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]);
4885 double angle=acos(cosangle/(radius*radius));
4886 tmp->rotate(end,vecPlane,angle);
4888 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4894 * This method is private because not easy to use for end user. This method is const contrary to
4895 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4896 * the coords sorted slice by slice.
4897 * \param isQuad specifies presence of quadratic cells.
4899 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4901 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4902 int nbOf2DCells(getNumberOfCells());
4903 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4904 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4905 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4907 newConnI->alloc(nbOf3DCells+1,1);
4908 int *newConnIPtr(newConnI->getPointer());
4910 std::vector<int> newc;
4911 for(int j=0;j<nbOf2DCells;j++)
4913 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4914 *newConnIPtr++=(int)newc.size();
4916 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4917 int *newConnPtr(newConn->getPointer());
4918 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4919 newConnIPtr=newConnI->getPointer();
4920 for(int iz=0;iz<nbOf1DCells;iz++)
4923 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4924 const int *posOfTypeOfCell(newConnIPtr);
4925 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4927 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4928 if(icell!=*posOfTypeOfCell)
4931 *newConnPtr=(*iter)+iz*deltaPerLev;
4942 ret->setConnectivity(newConn,newConnI,true);
4943 ret->setCoords(getCoords());
4948 * Checks if \a this mesh is constituted by only quadratic cells.
4949 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4950 * \throw If the coordinates array is not set.
4951 * \throw If the nodal connectivity of cells is not defined.
4953 bool MEDCouplingUMesh::isFullyQuadratic() const
4955 checkFullyDefined();
4957 int nbOfCells=getNumberOfCells();
4958 for(int i=0;i<nbOfCells && ret;i++)
4960 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4961 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4962 ret=cm.isQuadratic();
4968 * Checks if \a this mesh includes any quadratic cell.
4969 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4970 * \throw If the coordinates array is not set.
4971 * \throw If the nodal connectivity of cells is not defined.
4973 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4975 checkFullyDefined();
4977 int nbOfCells=getNumberOfCells();
4978 for(int i=0;i<nbOfCells && !ret;i++)
4980 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4981 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4982 ret=cm.isQuadratic();
4988 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4989 * this mesh, it remains unchanged.
4990 * \throw If the coordinates array is not set.
4991 * \throw If the nodal connectivity of cells is not defined.
4993 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4995 checkFullyDefined();
4996 int nbOfCells=getNumberOfCells();
4998 const int *iciptr=_nodal_connec_index->getConstPointer();
4999 for(int i=0;i<nbOfCells;i++)
5001 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5002 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5003 if(cm.isQuadratic())
5005 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5006 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5007 if(!cml.isDynamic())
5008 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5010 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5017 const int *icptr=_nodal_connec->getConstPointer();
5018 newConn->alloc(getMeshLength()-delta,1);
5019 newConnI->alloc(nbOfCells+1,1);
5020 int *ocptr=newConn->getPointer();
5021 int *ociptr=newConnI->getPointer();
5024 for(int i=0;i<nbOfCells;i++,ociptr++)
5026 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5027 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5028 if(!cm.isQuadratic())
5030 _types.insert(type);
5031 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5032 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5036 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5037 _types.insert(typel);
5038 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5039 int newNbOfNodes=cml.getNumberOfNodes();
5041 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5042 *ocptr++=(int)typel;
5043 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5044 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5047 setConnectivity(newConn,newConnI,false);
5051 * This method converts all linear cell in \a this to quadratic one.
5052 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5053 * 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)
5054 * 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.
5055 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5056 * end of the existing coordinates.
5058 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5059 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5060 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5062 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5064 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5066 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5068 DataArrayInt *conn=0,*connI=0;
5069 DataArrayDouble *coords=0;
5070 std::set<INTERP_KERNEL::NormalizedCellType> types;
5071 checkFullyDefined();
5072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5073 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5074 int meshDim=getMeshDimension();
5075 switch(conversionType)
5081 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5082 connSafe=conn; connISafe=connI; coordsSafe=coords;
5085 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5086 connSafe=conn; connISafe=connI; coordsSafe=coords;
5089 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5090 connSafe=conn; connISafe=connI; coordsSafe=coords;
5093 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5101 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5102 connSafe=conn; connISafe=connI; coordsSafe=coords;
5105 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5106 connSafe=conn; connISafe=connI; coordsSafe=coords;
5109 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5110 connSafe=conn; connISafe=connI; coordsSafe=coords;
5113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5118 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5120 setConnectivity(connSafe,connISafe,false);
5122 setCoords(coordsSafe);
5128 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5129 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5130 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5131 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5132 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5133 * This method can be seen as the opposite method of colinearize2D.
5134 * 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
5135 * to avoid to modify the numbering of existing nodes.
5137 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5138 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5139 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5140 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5141 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5142 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5143 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5145 * \sa buildDescendingConnectivity2
5147 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5148 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5150 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5151 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5152 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5153 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5154 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5155 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5156 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5157 //DataArrayInt *out0(0),*outi0(0);
5158 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5159 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5160 //out0s=out0s->buildUnique(); out0s->sort(true);
5165 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5166 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5167 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5169 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5171 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5175 int nbOfCells=getNumberOfCells();
5176 int nbOfNodes=getNumberOfNodes();
5177 const int *cPtr=_nodal_connec->getConstPointer();
5178 const int *icPtr=_nodal_connec_index->getConstPointer();
5179 int lastVal=0,offset=nbOfNodes;
5180 for(int i=0;i<nbOfCells;i++,icPtr++)
5182 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5183 if(type==INTERP_KERNEL::NORM_SEG2)
5185 types.insert(INTERP_KERNEL::NORM_SEG3);
5186 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5187 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5188 newConn->pushBackSilent(offset++);
5190 newConnI->pushBackSilent(lastVal);
5191 ret->pushBackSilent(i);
5196 lastVal+=(icPtr[1]-icPtr[0]);
5197 newConnI->pushBackSilent(lastVal);
5198 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5202 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5206 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
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5212 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5213 DataArrayInt *conn1D=0,*conn1DI=0;
5214 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5215 DataArrayDouble *coordsTmp=0;
5216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5217 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5219 const int *c1DPtr=conn1D->begin();
5220 const int *c1DIPtr=conn1DI->begin();
5221 int nbOfCells=getNumberOfCells();
5222 const int *cPtr=_nodal_connec->getConstPointer();
5223 const int *icPtr=_nodal_connec_index->getConstPointer();
5225 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5227 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5228 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5229 if(!cm.isQuadratic())
5231 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5232 types.insert(typ2); newConn->pushBackSilent(typ2);
5233 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5234 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5235 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5236 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5237 newConnI->pushBackSilent(lastVal);
5238 ret->pushBackSilent(i);
5243 lastVal+=(icPtr[1]-icPtr[0]);
5244 newConnI->pushBackSilent(lastVal);
5245 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5248 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5253 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5260 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5261 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5264 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5273 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5274 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5275 DataArrayInt *conn1D=0,*conn1DI=0;
5276 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5277 DataArrayDouble *coordsTmp=0;
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5281 const int *c1DPtr=conn1D->begin();
5282 const int *c1DIPtr=conn1DI->begin();
5283 int nbOfCells=getNumberOfCells();
5284 const int *cPtr=_nodal_connec->getConstPointer();
5285 const int *icPtr=_nodal_connec_index->getConstPointer();
5286 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5287 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5289 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5290 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5291 if(!cm.isQuadratic())
5293 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5294 types.insert(typ2); newConn->pushBackSilent(typ2);
5295 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5296 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5297 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5298 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5299 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5300 newConnI->pushBackSilent(lastVal);
5301 ret->pushBackSilent(i);
5306 lastVal+=(icPtr[1]-icPtr[0]);
5307 newConnI->pushBackSilent(lastVal);
5308 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5311 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5312 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5317 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5318 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5319 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5321 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5324 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5325 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5328 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5331 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5333 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5339 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5340 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5341 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5342 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5343 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5346 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5350 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5351 int nbOfCells=getNumberOfCells();
5352 const int *cPtr=_nodal_connec->getConstPointer();
5353 const int *icPtr=_nodal_connec_index->getConstPointer();
5354 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5355 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5357 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5358 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5359 if(!cm.isQuadratic())
5361 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5362 if(typ2==INTERP_KERNEL::NORM_ERROR)
5364 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5365 throw INTERP_KERNEL::Exception(oss.str().c_str());
5367 types.insert(typ2); newConn->pushBackSilent(typ2);
5368 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5369 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5370 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5371 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5373 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5374 int tmpPos=newConn->getNumberOfTuples();
5375 newConn->pushBackSilent(nodeId2);
5376 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5378 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5379 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5380 newConnI->pushBackSilent(lastVal);
5381 ret->pushBackSilent(i);
5386 lastVal+=(icPtr[1]-icPtr[0]);
5387 newConnI->pushBackSilent(lastVal);
5388 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5393 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5394 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5395 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5396 int *c=newConn->getPointer();
5397 const int *cI(newConnI->begin());
5398 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5399 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5400 offset=coordsTmp2Safe->getNumberOfTuples();
5401 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5402 c[cI[(*elt)+1]-1]+=offset;
5403 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5408 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5409 * so that the number of cells remains the same. Quadratic faces are converted to
5410 * polygons. This method works only for 2D meshes in
5411 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5412 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5413 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5414 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5415 * a polylinized edge constituting the input polygon.
5416 * \throw If the coordinates array is not set.
5417 * \throw If the nodal connectivity of cells is not defined.
5418 * \throw If \a this->getMeshDimension() != 2.
5419 * \throw If \a this->getSpaceDimension() != 2.
5421 void MEDCouplingUMesh::tessellate2D(double eps)
5423 checkFullyDefined();
5424 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5426 double epsa=fabs(eps);
5427 if(epsa<std::numeric_limits<double>::min())
5428 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 !");
5429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5433 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5434 revDesc1=0; revDescIndx1=0;
5435 mDesc->tessellate2DCurve(eps);
5436 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5437 setCoords(mDesc->getCoords());
5441 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5442 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5443 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5444 * a sub-divided edge.
5445 * \throw If the coordinates array is not set.
5446 * \throw If the nodal connectivity of cells is not defined.
5447 * \throw If \a this->getMeshDimension() != 1.
5448 * \throw If \a this->getSpaceDimension() != 2.
5450 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5452 checkFullyDefined();
5453 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5455 double epsa=fabs(eps);
5456 if(epsa<std::numeric_limits<double>::min())
5457 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 !");
5458 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5459 int nbCells=getNumberOfCells();
5460 int nbNodes=getNumberOfNodes();
5461 const int *conn=_nodal_connec->getConstPointer();
5462 const int *connI=_nodal_connec_index->getConstPointer();
5463 const double *coords=_coords->getConstPointer();
5464 std::vector<double> addCoo;
5465 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5467 newConnI->alloc(nbCells+1,1);
5468 int *newConnIPtr=newConnI->getPointer();
5471 INTERP_KERNEL::Node *tmp2[3];
5472 std::set<INTERP_KERNEL::NormalizedCellType> types;
5473 for(int i=0;i<nbCells;i++,newConnIPtr++)
5475 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5476 if(cm.isQuadratic())
5477 {//assert(connI[i+1]-connI[i]-1==3)
5478 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5479 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5480 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5481 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5482 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5485 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5486 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5488 newConnIPtr[1]=(int)newConn.size();
5492 types.insert(INTERP_KERNEL::NORM_SEG2);
5493 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5494 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5495 newConnIPtr[1]=newConnIPtr[0]+3;
5500 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5501 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5502 newConnIPtr[1]=newConnIPtr[0]+3;
5505 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5508 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5510 newConnArr->alloc((int)newConn.size(),1);
5511 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5512 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5513 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5514 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5515 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5516 std::copy(addCoo.begin(),addCoo.end(),work);
5517 DataArrayDouble::SetArrayIn(newCoords,_coords);
5522 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5523 * In addition, returns an array mapping new cells to old ones. <br>
5524 * This method typically increases the number of cells in \a this mesh
5525 * but the number of nodes remains \b unchanged.
5526 * That's why the 3D splitting policies
5527 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5528 * \param [in] policy - specifies a pattern used for splitting.
5529 * The semantic of \a policy is:
5530 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5531 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5532 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5533 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5536 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5537 * an id of old cell producing it. The caller is to delete this array using
5538 * decrRef() as it is no more needed.
5540 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5541 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5542 * and \a this->getMeshDimension() != 3.
5543 * \throw If \a policy is not one of the four discussed above.
5544 * \throw If the nodal connectivity of cells is not defined.
5545 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5547 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5552 return simplexizePol0();
5554 return simplexizePol1();
5555 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5556 return simplexizePlanarFace5();
5557 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5558 return simplexizePlanarFace6();
5560 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)");
5565 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5566 * - 1D: INTERP_KERNEL::NORM_SEG2
5567 * - 2D: INTERP_KERNEL::NORM_TRI3
5568 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5570 * This method is useful for users that need to use P1 field services as
5571 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5572 * All these methods need mesh support containing only simplex cells.
5573 * \return bool - \c true if there are only simplex cells in \a this mesh.
5574 * \throw If the coordinates array is not set.
5575 * \throw If the nodal connectivity of cells is not defined.
5576 * \throw If \a this->getMeshDimension() < 1.
5578 bool MEDCouplingUMesh::areOnlySimplexCells() const
5580 checkFullyDefined();
5581 int mdim=getMeshDimension();
5582 if(mdim<1 || mdim>3)
5583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5584 int nbCells=getNumberOfCells();
5585 const int *conn=_nodal_connec->getConstPointer();
5586 const int *connI=_nodal_connec_index->getConstPointer();
5587 for(int i=0;i<nbCells;i++)
5589 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5597 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5599 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5601 checkConnectivityFullyDefined();
5602 if(getMeshDimension()!=2)
5603 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5604 int nbOfCells=getNumberOfCells();
5605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5606 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5607 ret->alloc(nbOfCells+nbOfCutCells,1);
5608 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5609 int *retPt=ret->getPointer();
5610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5612 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5613 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5614 int *pt=newConn->getPointer();
5615 int *ptI=newConnI->getPointer();
5617 const int *oldc=_nodal_connec->getConstPointer();
5618 const int *ci=_nodal_connec_index->getConstPointer();
5619 for(int i=0;i<nbOfCells;i++,ci++)
5621 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5623 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5624 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5625 pt=std::copy(tmp,tmp+8,pt);
5634 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5635 ptI[1]=ptI[0]+ci[1]-ci[0];
5640 _nodal_connec->decrRef();
5641 _nodal_connec=newConn.retn();
5642 _nodal_connec_index->decrRef();
5643 _nodal_connec_index=newConnI.retn();
5650 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5652 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5654 checkConnectivityFullyDefined();
5655 if(getMeshDimension()!=2)
5656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5657 int nbOfCells=getNumberOfCells();
5658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5659 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5660 ret->alloc(nbOfCells+nbOfCutCells,1);
5661 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5662 int *retPt=ret->getPointer();
5663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5664 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5665 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5666 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5667 int *pt=newConn->getPointer();
5668 int *ptI=newConnI->getPointer();
5670 const int *oldc=_nodal_connec->getConstPointer();
5671 const int *ci=_nodal_connec_index->getConstPointer();
5672 for(int i=0;i<nbOfCells;i++,ci++)
5674 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5676 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5677 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5678 pt=std::copy(tmp,tmp+8,pt);
5687 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5688 ptI[1]=ptI[0]+ci[1]-ci[0];
5693 _nodal_connec->decrRef();
5694 _nodal_connec=newConn.retn();
5695 _nodal_connec_index->decrRef();
5696 _nodal_connec_index=newConnI.retn();
5703 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5705 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5707 checkConnectivityFullyDefined();
5708 if(getMeshDimension()!=3)
5709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5710 int nbOfCells=getNumberOfCells();
5711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5712 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5713 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5714 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5715 int *retPt=ret->getPointer();
5716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5717 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5718 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5719 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5720 int *pt=newConn->getPointer();
5721 int *ptI=newConnI->getPointer();
5723 const int *oldc=_nodal_connec->getConstPointer();
5724 const int *ci=_nodal_connec_index->getConstPointer();
5725 for(int i=0;i<nbOfCells;i++,ci++)
5727 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5729 for(int j=0;j<5;j++,pt+=5,ptI++)
5731 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5732 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];
5739 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5740 ptI[1]=ptI[0]+ci[1]-ci[0];
5745 _nodal_connec->decrRef();
5746 _nodal_connec=newConn.retn();
5747 _nodal_connec_index->decrRef();
5748 _nodal_connec_index=newConnI.retn();
5755 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5757 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5759 checkConnectivityFullyDefined();
5760 if(getMeshDimension()!=3)
5761 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5762 int nbOfCells=getNumberOfCells();
5763 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5764 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5765 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5766 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5767 int *retPt=ret->getPointer();
5768 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5769 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5770 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5771 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5772 int *pt=newConn->getPointer();
5773 int *ptI=newConnI->getPointer();
5775 const int *oldc=_nodal_connec->getConstPointer();
5776 const int *ci=_nodal_connec_index->getConstPointer();
5777 for(int i=0;i<nbOfCells;i++,ci++)
5779 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5781 for(int j=0;j<6;j++,pt+=5,ptI++)
5783 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5784 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];
5791 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5792 ptI[1]=ptI[0]+ci[1]-ci[0];
5797 _nodal_connec->decrRef();
5798 _nodal_connec=newConn.retn();
5799 _nodal_connec_index->decrRef();
5800 _nodal_connec_index=newConnI.retn();
5807 * 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.
5808 * This method completly ignore coordinates.
5809 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5810 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5811 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5812 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5814 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5816 checkFullyDefined();
5817 if(getMeshDimension()!=2)
5818 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5819 int nbOfCells=getNumberOfCells();
5820 int *connI=_nodal_connec_index->getPointer();
5822 for(int i=0;i<nbOfCells;i++,connI++)
5824 int offset=descIndex[i];
5825 int nbOfEdges=descIndex[i+1]-offset;
5827 bool ddirect=desc[offset+nbOfEdges-1]>0;
5828 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5829 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5830 for(int j=0;j<nbOfEdges;j++)
5832 bool direct=desc[offset+j]>0;
5833 int edgeId=std::abs(desc[offset+j])-1;
5834 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5836 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5837 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5838 int ref2=direct?id1:id2;
5841 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5842 newConnLgth+=nbOfSubNodes-1;
5847 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5848 throw INTERP_KERNEL::Exception(oss.str().c_str());
5853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5856 newConnLgth++;//+1 is for cell type
5857 connI[1]=newConnLgth;
5860 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5861 newConn->alloc(newConnLgth,1);
5862 int *work=newConn->getPointer();
5863 for(int i=0;i<nbOfCells;i++)
5865 *work++=INTERP_KERNEL::NORM_POLYGON;
5866 int offset=descIndex[i];
5867 int nbOfEdges=descIndex[i+1]-offset;
5868 for(int j=0;j<nbOfEdges;j++)
5870 bool direct=desc[offset+j]>0;
5871 int edgeId=std::abs(desc[offset+j])-1;
5873 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5876 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5877 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5878 work=std::copy(it,it+nbOfSubNodes-1,work);
5882 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5885 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5889 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5890 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5891 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5892 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5893 * so it can be useful to call mergeNodes() before calling this method.
5894 * \throw If \a this->getMeshDimension() <= 1.
5895 * \throw If the coordinates array is not set.
5896 * \throw If the nodal connectivity of cells is not defined.
5898 void MEDCouplingUMesh::convertDegeneratedCells()
5900 checkFullyDefined();
5901 if(getMeshDimension()<=1)
5902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5903 int nbOfCells=getNumberOfCells();
5906 int initMeshLgth=getMeshLength();
5907 int *conn=_nodal_connec->getPointer();
5908 int *index=_nodal_connec_index->getPointer();
5912 for(int i=0;i<nbOfCells;i++)
5914 lgthOfCurCell=index[i+1]-posOfCurCell;
5915 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5917 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5918 conn+newPos+1,newLgth);
5919 conn[newPos]=newType;
5921 posOfCurCell=index[i+1];
5924 if(newPos!=initMeshLgth)
5925 _nodal_connec->reAlloc(newPos);
5930 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5931 * A cell is considered to be oriented correctly if an angle between its
5932 * normal vector and a given vector is less than \c PI / \c 2.
5933 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5935 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5937 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5938 * is not cleared before filling in.
5939 * \throw If \a this->getMeshDimension() != 2.
5940 * \throw If \a this->getSpaceDimension() != 3.
5942 * \if ENABLE_EXAMPLES
5943 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5944 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5947 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5949 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5950 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5951 int nbOfCells=getNumberOfCells();
5952 const int *conn=_nodal_connec->getConstPointer();
5953 const int *connI=_nodal_connec_index->getConstPointer();
5954 const double *coordsPtr=_coords->getConstPointer();
5955 for(int i=0;i<nbOfCells;i++)
5957 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5958 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5960 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5961 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5968 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5969 * considered to be oriented correctly if an angle between its normal vector and a
5970 * given vector is less than \c PI / \c 2.
5971 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5973 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5975 * \throw If \a this->getMeshDimension() != 2.
5976 * \throw If \a this->getSpaceDimension() != 3.
5978 * \if ENABLE_EXAMPLES
5979 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5980 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5983 * \sa changeOrientationOfCells
5985 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5987 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5988 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5989 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5990 const int *connI(_nodal_connec_index->getConstPointer());
5991 const double *coordsPtr(_coords->getConstPointer());
5992 bool isModified(false);
5993 for(int i=0;i<nbOfCells;i++)
5995 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5996 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5998 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5999 bool isQuadratic(cm.isQuadratic());
6000 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6003 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6008 _nodal_connec->declareAsNew();
6013 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6015 * \sa orientCorrectly2DCells
6017 void MEDCouplingUMesh::changeOrientationOfCells()
6019 int mdim(getMeshDimension());
6020 if(mdim!=2 && mdim!=1)
6021 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6022 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6023 const int *connI(_nodal_connec_index->getConstPointer());
6026 for(int i=0;i<nbOfCells;i++)
6028 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6029 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6030 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6035 for(int i=0;i<nbOfCells;i++)
6037 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6038 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6039 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6045 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6046 * oriented facets. The normal vector of the facet should point out of the cell.
6047 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6048 * is not cleared before filling in.
6049 * \throw If \a this->getMeshDimension() != 3.
6050 * \throw If \a this->getSpaceDimension() != 3.
6051 * \throw If the coordinates array is not set.
6052 * \throw If the nodal connectivity of cells is not defined.
6054 * \if ENABLE_EXAMPLES
6055 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6056 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6059 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6061 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6062 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6063 int nbOfCells=getNumberOfCells();
6064 const int *conn=_nodal_connec->getConstPointer();
6065 const int *connI=_nodal_connec_index->getConstPointer();
6066 const double *coordsPtr=_coords->getConstPointer();
6067 for(int i=0;i<nbOfCells;i++)
6069 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6070 if(type==INTERP_KERNEL::NORM_POLYHED)
6072 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6079 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
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.
6085 * \throw If the reparation fails.
6087 * \if ENABLE_EXAMPLES
6088 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6089 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6091 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6093 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6095 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6096 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6097 int nbOfCells=getNumberOfCells();
6098 int *conn=_nodal_connec->getPointer();
6099 const int *connI=_nodal_connec_index->getConstPointer();
6100 const double *coordsPtr=_coords->getConstPointer();
6101 for(int i=0;i<nbOfCells;i++)
6103 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6104 if(type==INTERP_KERNEL::NORM_POLYHED)
6108 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6109 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6111 catch(INTERP_KERNEL::Exception& e)
6113 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6114 throw INTERP_KERNEL::Exception(oss.str().c_str());
6122 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6123 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6124 * according to which the first facet of the cell should be oriented to have the normal vector
6125 * pointing out of cell.
6126 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6127 * cells. The caller is to delete this array using decrRef() as it is no more
6129 * \throw If \a this->getMeshDimension() != 3.
6130 * \throw If \a this->getSpaceDimension() != 3.
6131 * \throw If the coordinates array is not set.
6132 * \throw If the nodal connectivity of cells is not defined.
6134 * \if ENABLE_EXAMPLES
6135 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6136 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6138 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6140 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6142 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6143 if(getMeshDimension()!=3)
6144 throw INTERP_KERNEL::Exception(msg);
6145 int spaceDim=getSpaceDimension();
6147 throw INTERP_KERNEL::Exception(msg);
6149 int nbOfCells=getNumberOfCells();
6150 int *conn=_nodal_connec->getPointer();
6151 const int *connI=_nodal_connec_index->getConstPointer();
6152 const double *coo=getCoords()->getConstPointer();
6153 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6154 for(int i=0;i<nbOfCells;i++)
6156 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6157 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6159 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6161 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6162 cells->pushBackSilent(i);
6166 return cells.retn();
6170 * This method is a faster method to correct orientation of all 3D cells in \a this.
6171 * 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.
6172 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6174 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6175 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6177 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6179 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6180 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6181 int nbOfCells=getNumberOfCells();
6182 int *conn=_nodal_connec->getPointer();
6183 const int *connI=_nodal_connec_index->getConstPointer();
6184 const double *coordsPtr=_coords->getConstPointer();
6185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6186 for(int i=0;i<nbOfCells;i++)
6188 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6191 case INTERP_KERNEL::NORM_TETRA4:
6193 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6195 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6196 ret->pushBackSilent(i);
6200 case INTERP_KERNEL::NORM_PYRA5:
6202 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6204 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6205 ret->pushBackSilent(i);
6209 case INTERP_KERNEL::NORM_PENTA6:
6210 case INTERP_KERNEL::NORM_HEXA8:
6211 case INTERP_KERNEL::NORM_HEXGP12:
6213 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6215 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6216 ret->pushBackSilent(i);
6220 case INTERP_KERNEL::NORM_POLYHED:
6222 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6224 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6225 ret->pushBackSilent(i);
6230 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 !");
6238 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6239 * If it is not the case an exception will be thrown.
6240 * This method is fast because the first cell of \a this is used to compute the plane.
6241 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6242 * \param pos output of size at least 3 used to store a point owned of searched plane.
6244 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6246 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6247 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6248 const int *conn=_nodal_connec->getConstPointer();
6249 const int *connI=_nodal_connec_index->getConstPointer();
6250 const double *coordsPtr=_coords->getConstPointer();
6251 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6252 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6256 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6257 * cells. Currently cells of the following types are treated:
6258 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6259 * For a cell of other type an exception is thrown.
6260 * Space dimension of a 2D mesh can be either 2 or 3.
6261 * The Edge Ratio of a cell \f$t\f$ is:
6262 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6263 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6264 * the smallest edge lengths of \f$t\f$.
6265 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6266 * cells and one time, lying on \a this mesh. The caller is to delete this
6267 * field using decrRef() as it is no more needed.
6268 * \throw If the coordinates array is not set.
6269 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6270 * \throw If the connectivity data array has more than one component.
6271 * \throw If the connectivity data array has a named component.
6272 * \throw If the connectivity index data array has more than one component.
6273 * \throw If the connectivity index data array has a named component.
6274 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6275 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6276 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6278 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6281 int spaceDim=getSpaceDimension();
6282 int meshDim=getMeshDimension();
6283 if(spaceDim!=2 && spaceDim!=3)
6284 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6285 if(meshDim!=2 && meshDim!=3)
6286 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6287 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6289 int nbOfCells=getNumberOfCells();
6290 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6291 arr->alloc(nbOfCells,1);
6292 double *pt=arr->getPointer();
6293 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6294 const int *conn=_nodal_connec->getConstPointer();
6295 const int *connI=_nodal_connec_index->getConstPointer();
6296 const double *coo=_coords->getConstPointer();
6298 for(int i=0;i<nbOfCells;i++,pt++)
6300 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6303 case INTERP_KERNEL::NORM_TRI3:
6305 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6306 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6309 case INTERP_KERNEL::NORM_QUAD4:
6311 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6312 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6315 case INTERP_KERNEL::NORM_TETRA4:
6317 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6318 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6322 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6324 conn+=connI[i+1]-connI[i];
6326 ret->setName("EdgeRatio");
6327 ret->synchronizeTimeWithSupport();
6332 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6333 * cells. Currently cells of the following types are treated:
6334 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6335 * For a cell of other type an exception is thrown.
6336 * Space dimension of a 2D mesh can be either 2 or 3.
6337 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6338 * cells and one time, lying on \a this mesh. The caller is to delete this
6339 * field using decrRef() as it is no more needed.
6340 * \throw If the coordinates array is not set.
6341 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6342 * \throw If the connectivity data array has more than one component.
6343 * \throw If the connectivity data array has a named component.
6344 * \throw If the connectivity index data array has more than one component.
6345 * \throw If the connectivity index data array has a named component.
6346 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6347 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6348 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6350 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6353 int spaceDim=getSpaceDimension();
6354 int meshDim=getMeshDimension();
6355 if(spaceDim!=2 && spaceDim!=3)
6356 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6357 if(meshDim!=2 && meshDim!=3)
6358 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6359 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6361 int nbOfCells=getNumberOfCells();
6362 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6363 arr->alloc(nbOfCells,1);
6364 double *pt=arr->getPointer();
6365 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6366 const int *conn=_nodal_connec->getConstPointer();
6367 const int *connI=_nodal_connec_index->getConstPointer();
6368 const double *coo=_coords->getConstPointer();
6370 for(int i=0;i<nbOfCells;i++,pt++)
6372 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6375 case INTERP_KERNEL::NORM_TRI3:
6377 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6378 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6381 case INTERP_KERNEL::NORM_QUAD4:
6383 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6384 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6387 case INTERP_KERNEL::NORM_TETRA4:
6389 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6390 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6394 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6396 conn+=connI[i+1]-connI[i];
6398 ret->setName("AspectRatio");
6399 ret->synchronizeTimeWithSupport();
6404 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6405 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6406 * treated: INTERP_KERNEL::NORM_QUAD4.
6407 * For a cell of other type an exception is thrown.
6408 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6409 * cells and one time, lying on \a this mesh. The caller is to delete this
6410 * field using decrRef() as it is no more needed.
6411 * \throw If the coordinates array is not set.
6412 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6413 * \throw If the connectivity data array has more than one component.
6414 * \throw If the connectivity data array has a named component.
6415 * \throw If the connectivity index data array has more than one component.
6416 * \throw If the connectivity index data array has a named component.
6417 * \throw If \a this->getMeshDimension() != 2.
6418 * \throw If \a this->getSpaceDimension() != 3.
6419 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6421 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6424 int spaceDim=getSpaceDimension();
6425 int meshDim=getMeshDimension();
6427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6429 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6430 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6432 int nbOfCells=getNumberOfCells();
6433 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6434 arr->alloc(nbOfCells,1);
6435 double *pt=arr->getPointer();
6436 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6437 const int *conn=_nodal_connec->getConstPointer();
6438 const int *connI=_nodal_connec_index->getConstPointer();
6439 const double *coo=_coords->getConstPointer();
6441 for(int i=0;i<nbOfCells;i++,pt++)
6443 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6446 case INTERP_KERNEL::NORM_QUAD4:
6448 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6449 *pt=INTERP_KERNEL::quadWarp(tmp);
6453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6455 conn+=connI[i+1]-connI[i];
6457 ret->setName("Warp");
6458 ret->synchronizeTimeWithSupport();
6464 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6465 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6466 * treated: INTERP_KERNEL::NORM_QUAD4.
6467 * For a cell of other type an exception is thrown.
6468 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6469 * cells and one time, lying on \a this mesh. The caller is to delete this
6470 * field using decrRef() as it is no more needed.
6471 * \throw If the coordinates array is not set.
6472 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6473 * \throw If the connectivity data array has more than one component.
6474 * \throw If the connectivity data array has a named component.
6475 * \throw If the connectivity index data array has more than one component.
6476 * \throw If the connectivity index data array has a named component.
6477 * \throw If \a this->getMeshDimension() != 2.
6478 * \throw If \a this->getSpaceDimension() != 3.
6479 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6481 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6484 int spaceDim=getSpaceDimension();
6485 int meshDim=getMeshDimension();
6487 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6489 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6490 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6492 int nbOfCells=getNumberOfCells();
6493 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6494 arr->alloc(nbOfCells,1);
6495 double *pt=arr->getPointer();
6496 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6497 const int *conn=_nodal_connec->getConstPointer();
6498 const int *connI=_nodal_connec_index->getConstPointer();
6499 const double *coo=_coords->getConstPointer();
6501 for(int i=0;i<nbOfCells;i++,pt++)
6503 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6506 case INTERP_KERNEL::NORM_QUAD4:
6508 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6509 *pt=INTERP_KERNEL::quadSkew(tmp);
6513 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6515 conn+=connI[i+1]-connI[i];
6517 ret->setName("Skew");
6518 ret->synchronizeTimeWithSupport();
6523 * 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.
6525 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6527 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6529 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6532 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6534 std::set<INTERP_KERNEL::NormalizedCellType> types;
6535 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6536 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6537 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6538 arr->alloc(nbCells,1);
6539 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6541 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6542 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6543 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6546 ret->setName("Diameter");
6551 * This method aggregate the bbox of each cell and put it into bbox parameter.
6553 * \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)
6554 * For all other cases this input parameter is ignored.
6555 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6557 * \throw If \a this is not fully set (coordinates and connectivity).
6558 * \throw If a cell in \a this has no valid nodeId.
6559 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6561 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6563 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6564 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.
6565 return getBoundingBoxForBBTreeFast();
6566 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6568 bool presenceOfQuadratic(false);
6569 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6571 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6572 if(cm.isQuadratic())
6573 presenceOfQuadratic=true;
6575 if(!presenceOfQuadratic)
6576 return getBoundingBoxForBBTreeFast();
6577 if(mDim==2 && sDim==2)
6578 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6580 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6582 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) !");
6586 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6587 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6589 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6591 * \throw If \a this is not fully set (coordinates and connectivity).
6592 * \throw If a cell in \a this has no valid nodeId.
6594 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6596 checkFullyDefined();
6597 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6598 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6599 double *bbox(ret->getPointer());
6600 for(int i=0;i<nbOfCells*spaceDim;i++)
6602 bbox[2*i]=std::numeric_limits<double>::max();
6603 bbox[2*i+1]=-std::numeric_limits<double>::max();
6605 const double *coordsPtr(_coords->getConstPointer());
6606 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6607 for(int i=0;i<nbOfCells;i++)
6609 int offset=connI[i]+1;
6610 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6611 for(int j=0;j<nbOfNodesForCell;j++)
6613 int nodeId=conn[offset+j];
6614 if(nodeId>=0 && nodeId<nbOfNodes)
6616 for(int k=0;k<spaceDim;k++)
6618 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6619 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6626 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6627 throw INTERP_KERNEL::Exception(oss.str().c_str());
6634 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6635 * useful for 2D meshes having quadratic cells
6636 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6637 * the two extremities of the arc of circle).
6639 * \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)
6640 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6641 * \throw If \a this is not fully defined.
6642 * \throw If \a this is not a mesh with meshDimension equal to 2.
6643 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6644 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6646 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6648 checkFullyDefined();
6649 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6650 if(spaceDim!=2 || mDim!=2)
6651 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!");
6652 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6653 double *bbox(ret->getPointer());
6654 const double *coords(_coords->getConstPointer());
6655 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6656 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6658 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6659 int sz(connI[1]-connI[0]-1);
6660 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6661 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6662 INTERP_KERNEL::QuadraticPolygon *pol(0);
6663 for(int j=0;j<sz;j++)
6665 int nodeId(conn[*connI+1+j]);
6666 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6668 if(!cm.isQuadratic())
6669 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6671 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6672 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6673 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6679 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6680 * useful for 2D meshes having quadratic cells
6681 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6682 * the two extremities of the arc of circle).
6684 * \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)
6685 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6686 * \throw If \a this is not fully defined.
6687 * \throw If \a this is not a mesh with meshDimension equal to 1.
6688 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6689 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6691 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6693 checkFullyDefined();
6694 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6695 if(spaceDim!=2 || mDim!=1)
6696 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!");
6697 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6698 double *bbox(ret->getPointer());
6699 const double *coords(_coords->getConstPointer());
6700 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6701 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6703 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6704 int sz(connI[1]-connI[0]-1);
6705 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6706 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6707 INTERP_KERNEL::Edge *edge(0);
6708 for(int j=0;j<sz;j++)
6710 int nodeId(conn[*connI+1+j]);
6711 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6713 if(!cm.isQuadratic())
6714 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6716 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6717 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6718 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6725 namespace ParaMEDMEMImpl
6730 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6731 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6740 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6741 bool operator() (const int& pos) { return _conn[pos]==_val; }
6751 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6752 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6753 * \a this is composed in cell types.
6754 * The returned array is of size 3*n where n is the number of different types present in \a this.
6755 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6756 * This parameter is kept only for compatibility with other methode listed above.
6758 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6760 checkConnectivityFullyDefined();
6761 const int *conn=_nodal_connec->getConstPointer();
6762 const int *connI=_nodal_connec_index->getConstPointer();
6763 const int *work=connI;
6764 int nbOfCells=getNumberOfCells();
6765 std::size_t n=getAllGeoTypes().size();
6766 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6767 std::set<INTERP_KERNEL::NormalizedCellType> types;
6768 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6770 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6771 if(types.find(typ)!=types.end())
6773 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6774 oss << " is not contiguous !";
6775 throw INTERP_KERNEL::Exception(oss.str().c_str());
6779 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6780 ret[3*i+1]=(int)std::distance(work,work2);
6787 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6788 * only for types cell, type node is not managed.
6789 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6790 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6791 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6792 * If 2 or more same geometric type is in \a code and exception is thrown too.
6794 * This method firstly checks
6795 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6796 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6797 * an exception is thrown too.
6799 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6800 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6801 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6803 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6806 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6807 std::size_t sz=code.size();
6810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6811 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6813 bool isNoPflUsed=true;
6814 for(std::size_t i=0;i<n;i++)
6815 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6817 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6819 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6820 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6821 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6827 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6828 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6829 if(types.size()==_types.size())
6832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6834 int *retPtr=ret->getPointer();
6835 const int *connI=_nodal_connec_index->getConstPointer();
6836 const int *conn=_nodal_connec->getConstPointer();
6837 int nbOfCells=getNumberOfCells();
6840 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6842 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6843 int offset=(int)std::distance(connI,i);
6844 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6845 int nbOfCellsOfCurType=(int)std::distance(i,j);
6846 if(code[3*kk+2]==-1)
6847 for(int k=0;k<nbOfCellsOfCurType;k++)
6851 int idInIdsPerType=code[3*kk+2];
6852 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6854 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6857 zePfl->checkAllocated();
6858 if(zePfl->getNumberOfComponents()==1)
6860 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6862 if(*k>=0 && *k<nbOfCellsOfCurType)
6863 *retPtr=(*k)+offset;
6866 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6867 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6868 throw INTERP_KERNEL::Exception(oss.str().c_str());
6873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6880 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6881 oss << " should be in [0," << idsPerType.size() << ") !";
6882 throw INTERP_KERNEL::Exception(oss.str().c_str());
6891 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6892 * 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.
6893 * 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.
6894 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6896 * \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.
6897 * \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,
6898 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6899 * \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.
6900 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6901 * \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
6903 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6906 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6907 if(profile->getNumberOfComponents()!=1)
6908 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6909 checkConnectivityFullyDefined();
6910 const int *conn=_nodal_connec->getConstPointer();
6911 const int *connI=_nodal_connec_index->getConstPointer();
6912 int nbOfCells=getNumberOfCells();
6913 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6914 std::vector<int> typeRangeVals(1);
6915 for(const int *i=connI;i!=connI+nbOfCells;)
6917 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6918 if(std::find(types.begin(),types.end(),curType)!=types.end())
6920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6922 types.push_back(curType);
6923 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6924 typeRangeVals.push_back((int)std::distance(connI,i));
6927 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6928 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6930 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6931 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6933 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6934 code.resize(3*nbOfCastsFinal);
6935 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6936 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6937 for(int i=0;i<nbOfCastsFinal;i++)
6939 int castId=castsPresent->getIJ(i,0);
6940 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6941 idsInPflPerType2.push_back(tmp3);
6942 code[3*i]=(int)types[castId];
6943 code[3*i+1]=tmp3->getNumberOfTuples();
6944 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6945 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6947 tmp4->copyStringInfoFrom(*profile);
6948 idsPerType2.push_back(tmp4);
6949 code[3*i+2]=(int)idsPerType2.size()-1;
6956 std::size_t sz2=idsInPflPerType2.size();
6957 idsInPflPerType.resize(sz2);
6958 for(std::size_t i=0;i<sz2;i++)
6960 DataArrayInt *locDa=idsInPflPerType2[i];
6962 idsInPflPerType[i]=locDa;
6964 std::size_t sz=idsPerType2.size();
6965 idsPerType.resize(sz);
6966 for(std::size_t i=0;i<sz;i++)
6968 DataArrayInt *locDa=idsPerType2[i];
6970 idsPerType[i]=locDa;
6975 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6976 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6977 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6978 * 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.
6980 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6982 checkFullyDefined();
6983 nM1LevMesh->checkFullyDefined();
6984 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6986 if(_coords!=nM1LevMesh->getCoords())
6987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6990 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6991 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6992 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6993 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6994 tmp->setConnectivity(tmp0,tmp1);
6995 tmp->renumberCells(ret0->getConstPointer(),false);
6996 revDesc=tmp->getNodalConnectivity();
6997 revDescIndx=tmp->getNodalConnectivityIndex();
6998 DataArrayInt *ret=0;
6999 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7002 ret->getMaxValue(tmp2);
7004 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7005 throw INTERP_KERNEL::Exception(oss.str().c_str());
7010 revDescIndx->incrRef();
7013 meshnM1Old2New=ret0;
7018 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7019 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7020 * in "Old to New" mode.
7021 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7022 * this array using decrRef() as it is no more needed.
7023 * \throw If the nodal connectivity of cells is not defined.
7025 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7027 checkConnectivityFullyDefined();
7028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7029 renumberCells(ret->getConstPointer(),false);
7034 * This methods checks that cells are sorted by their types.
7035 * This method makes asumption (no check) that connectivity is correctly set before calling.
7037 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7039 checkFullyDefined();
7040 const int *conn=_nodal_connec->getConstPointer();
7041 const int *connI=_nodal_connec_index->getConstPointer();
7042 int nbOfCells=getNumberOfCells();
7043 std::set<INTERP_KERNEL::NormalizedCellType> types;
7044 for(const int *i=connI;i!=connI+nbOfCells;)
7046 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7047 if(types.find(curType)!=types.end())
7049 types.insert(curType);
7050 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7056 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7057 * The geometric type order is specified by MED file.
7059 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7061 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7063 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7067 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7068 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7069 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7070 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7072 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7074 checkFullyDefined();
7075 const int *conn=_nodal_connec->getConstPointer();
7076 const int *connI=_nodal_connec_index->getConstPointer();
7077 int nbOfCells=getNumberOfCells();
7081 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7082 for(const int *i=connI;i!=connI+nbOfCells;)
7084 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7085 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7086 if(isTypeExists!=orderEnd)
7088 int pos=(int)std::distance(orderBg,isTypeExists);
7092 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7096 if(sg.find(curType)==sg.end())
7098 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7109 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7110 * 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
7111 * 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'.
7113 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7115 checkConnectivityFullyDefined();
7116 int nbOfCells=getNumberOfCells();
7117 const int *conn=_nodal_connec->getConstPointer();
7118 const int *connI=_nodal_connec_index->getConstPointer();
7119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7120 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7121 tmpa->alloc(nbOfCells,1);
7122 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7123 tmpb->fillWithZero();
7124 int *tmp=tmpa->getPointer();
7125 int *tmp2=tmpb->getPointer();
7126 for(const int *i=connI;i!=connI+nbOfCells;i++)
7128 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7131 int pos=(int)std::distance(orderBg,where);
7133 tmp[std::distance(connI,i)]=pos;
7137 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7138 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7139 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7140 throw INTERP_KERNEL::Exception(oss.str().c_str());
7143 nbPerType=tmpb.retn();
7148 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7150 * \return a new object containing the old to new correspondance.
7152 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7154 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7156 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7160 * 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.
7161 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7162 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7163 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7165 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7167 DataArrayInt *nbPerType=0;
7168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7169 nbPerType->decrRef();
7170 return tmpa->buildPermArrPerLevel();
7174 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7175 * The number of cells remains unchanged after the call of this method.
7176 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7177 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7179 * \return the array giving the correspondance old to new.
7181 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7183 checkFullyDefined();
7185 const int *conn=_nodal_connec->getConstPointer();
7186 const int *connI=_nodal_connec_index->getConstPointer();
7187 int nbOfCells=getNumberOfCells();
7188 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7189 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7190 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7192 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7193 types.push_back(curType);
7194 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7196 DataArrayInt *ret=DataArrayInt::New();
7197 ret->alloc(nbOfCells,1);
7198 int *retPtr=ret->getPointer();
7199 std::fill(retPtr,retPtr+nbOfCells,-1);
7201 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7203 for(const int *i=connI;i!=connI+nbOfCells;i++)
7204 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7205 retPtr[std::distance(connI,i)]=newCellId++;
7207 renumberCells(retPtr,false);
7212 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7213 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7214 * This method makes asumption that connectivity is correctly set before calling.
7216 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7218 checkConnectivityFullyDefined();
7219 const int *conn=_nodal_connec->getConstPointer();
7220 const int *connI=_nodal_connec_index->getConstPointer();
7221 int nbOfCells=getNumberOfCells();
7222 std::vector<MEDCouplingUMesh *> ret;
7223 for(const int *i=connI;i!=connI+nbOfCells;)
7225 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7226 int beginCellId=(int)std::distance(connI,i);
7227 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7228 int endCellId=(int)std::distance(connI,i);
7229 int sz=endCellId-beginCellId;
7230 int *cells=new int[sz];
7231 for(int j=0;j<sz;j++)
7232 cells[j]=beginCellId+j;
7233 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7241 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7242 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7243 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7245 * \return a newly allocated instance, that the caller must manage.
7246 * \throw If \a this contains more than one geometric type.
7247 * \throw If the nodal connectivity of \a this is not fully defined.
7248 * \throw If the internal data is not coherent.
7250 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7252 checkConnectivityFullyDefined();
7253 if(_types.size()!=1)
7254 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7255 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7256 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7257 ret->setCoords(getCoords());
7258 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7262 retC->setNodalConnectivity(c);
7266 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7268 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7269 DataArrayInt *c=0,*ci=0;
7270 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7272 retD->setNodalConnectivity(cs,cis);
7277 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7279 checkConnectivityFullyDefined();
7280 if(_types.size()!=1)
7281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7282 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7283 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7286 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7287 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7288 throw INTERP_KERNEL::Exception(oss.str().c_str());
7290 int nbCells=getNumberOfCells();
7292 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7294 int *outPtr=connOut->getPointer();
7295 const int *conn=_nodal_connec->begin();
7296 const int *connI=_nodal_connec_index->begin();
7298 for(int i=0;i<nbCells;i++,connI++)
7300 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7301 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7304 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 << ") !";
7305 throw INTERP_KERNEL::Exception(oss.str().c_str());
7308 return connOut.retn();
7311 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7313 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7314 checkConnectivityFullyDefined();
7315 if(_types.size()!=1)
7316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7317 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7319 throw INTERP_KERNEL::Exception(msg0);
7320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7321 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7322 int *cp(c->getPointer()),*cip(ci->getPointer());
7323 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7325 for(int i=0;i<nbCells;i++,cip++,incip++)
7327 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7328 int delta(stop-strt);
7331 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7332 cp=std::copy(incp+strt,incp+stop,cp);
7334 throw INTERP_KERNEL::Exception(msg0);
7337 throw INTERP_KERNEL::Exception(msg0);
7338 cip[1]=cip[0]+delta;
7340 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7344 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7345 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7346 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7347 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7348 * are not used here to avoid the build of big permutation array.
7350 * \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
7351 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7352 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7353 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7354 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7355 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7356 * \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
7357 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7359 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7360 DataArrayInt *&szOfCellGrpOfSameType,
7361 DataArrayInt *&idInMsOfCellGrpOfSameType)
7363 std::vector<const MEDCouplingUMesh *> ms2;
7364 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7367 (*it)->checkConnectivityFullyDefined();
7371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7372 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7373 int meshDim=ms2[0]->getMeshDimension();
7374 std::vector<const MEDCouplingUMesh *> m1ssm;
7375 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7377 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7378 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7381 ret1->alloc(0,1); ret2->alloc(0,1);
7382 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7384 if(meshDim!=(*it)->getMeshDimension())
7385 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7386 if(refCoo!=(*it)->getCoords())
7387 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7388 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7389 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7390 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7391 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7393 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7394 m1ssmSingleAuto.push_back(singleCell);
7395 m1ssmSingle.push_back(singleCell);
7396 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7399 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7401 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7402 for(std::size_t i=0;i<m1ssm.size();i++)
7403 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7404 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7405 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7406 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7411 * This method returns a newly created DataArrayInt instance.
7412 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7414 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7416 checkFullyDefined();
7417 const int *conn=_nodal_connec->getConstPointer();
7418 const int *connIndex=_nodal_connec_index->getConstPointer();
7419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7420 for(const int *w=begin;w!=end;w++)
7421 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7422 ret->pushBackSilent(*w);
7427 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7428 * are in [0:getNumberOfCells())
7430 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7432 checkFullyDefined();
7433 const int *conn=_nodal_connec->getConstPointer();
7434 const int *connI=_nodal_connec_index->getConstPointer();
7435 int nbOfCells=getNumberOfCells();
7436 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7437 int *tmp=new int[nbOfCells];
7438 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7441 for(const int *i=connI;i!=connI+nbOfCells;i++)
7442 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7443 tmp[std::distance(connI,i)]=j++;
7445 DataArrayInt *ret=DataArrayInt::New();
7446 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7447 ret->copyStringInfoFrom(*da);
7448 int *retPtr=ret->getPointer();
7449 const int *daPtr=da->getConstPointer();
7450 int nbOfElems=da->getNbOfElems();
7451 for(int k=0;k<nbOfElems;k++)
7452 retPtr[k]=tmp[daPtr[k]];
7458 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7459 * This method \b works \b for mesh sorted by type.
7460 * cells whose ids is in 'idsPerGeoType' array.
7461 * This method conserves coords and name of mesh.
7463 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7465 std::vector<int> code=getDistributionOfTypes();
7466 std::size_t nOfTypesInThis=code.size()/3;
7467 int sz=0,szOfType=0;
7468 for(std::size_t i=0;i<nOfTypesInThis;i++)
7473 szOfType=code[3*i+1];
7475 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7476 if(*work<0 || *work>=szOfType)
7478 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7479 oss << ". It should be in [0," << szOfType << ") !";
7480 throw INTERP_KERNEL::Exception(oss.str().c_str());
7482 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7483 int *idsPtr=idsTokeep->getPointer();
7485 for(std::size_t i=0;i<nOfTypesInThis;i++)
7488 for(int j=0;j<code[3*i+1];j++)
7491 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7492 offset+=code[3*i+1];
7494 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7495 ret->copyTinyInfoFrom(this);
7500 * This method returns a vector of size 'this->getNumberOfCells()'.
7501 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7503 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7505 int ncell=getNumberOfCells();
7506 std::vector<bool> ret(ncell);
7507 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7508 const int *c=getNodalConnectivity()->getConstPointer();
7509 for(int i=0;i<ncell;i++)
7511 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7512 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7513 ret[i]=cm.isQuadratic();
7519 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7521 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7523 if(other->getType()!=UNSTRUCTURED)
7524 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7525 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7526 return MergeUMeshes(this,otherC);
7530 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7531 * computed by averaging coordinates of cell nodes, so this method is not a right
7532 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7533 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7534 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7535 * components. The caller is to delete this array using decrRef() as it is
7537 * \throw If the coordinates array is not set.
7538 * \throw If the nodal connectivity of cells is not defined.
7539 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7541 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7543 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7544 int spaceDim=getSpaceDimension();
7545 int nbOfCells=getNumberOfCells();
7546 ret->alloc(nbOfCells,spaceDim);
7547 ret->copyStringInfoFrom(*getCoords());
7548 double *ptToFill=ret->getPointer();
7549 const int *nodal=_nodal_connec->getConstPointer();
7550 const int *nodalI=_nodal_connec_index->getConstPointer();
7551 const double *coor=_coords->getConstPointer();
7552 for(int i=0;i<nbOfCells;i++)
7554 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7555 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7562 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7563 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7565 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7566 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7568 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7569 * \throw If \a this is not fully defined (coordinates and connectivity)
7570 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7572 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7574 checkFullyDefined();
7575 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7576 int spaceDim=getSpaceDimension();
7577 int nbOfCells=getNumberOfCells();
7578 int nbOfNodes=getNumberOfNodes();
7579 ret->alloc(nbOfCells,spaceDim);
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++,ptToFill+=spaceDim)
7586 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7587 std::fill(ptToFill,ptToFill+spaceDim,0.);
7588 if(type!=INTERP_KERNEL::NORM_POLYHED)
7590 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7592 if(*conn>=0 && *conn<nbOfNodes)
7593 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7596 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7597 throw INTERP_KERNEL::Exception(oss.str().c_str());
7600 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7601 if(nbOfNodesInCell>0)
7602 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7605 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7606 throw INTERP_KERNEL::Exception(oss.str().c_str());
7611 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7613 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7615 if(*it>=0 && *it<nbOfNodes)
7616 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7619 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7620 throw INTERP_KERNEL::Exception(oss.str().c_str());
7624 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7627 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7628 throw INTERP_KERNEL::Exception(oss.str().c_str());
7636 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7637 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7638 * are specified via an array of cell ids.
7639 * \warning Validity of the specified cell ids is not checked!
7640 * Valid range is [ 0, \a this->getNumberOfCells() ).
7641 * \param [in] begin - an array of cell ids of interest.
7642 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7643 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7644 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7645 * caller is to delete this array using decrRef() as it is no more needed.
7646 * \throw If the coordinates array is not set.
7647 * \throw If the nodal connectivity of cells is not defined.
7649 * \if ENABLE_EXAMPLES
7650 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7651 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7654 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7656 DataArrayDouble *ret=DataArrayDouble::New();
7657 int spaceDim=getSpaceDimension();
7658 int nbOfTuple=(int)std::distance(begin,end);
7659 ret->alloc(nbOfTuple,spaceDim);
7660 double *ptToFill=ret->getPointer();
7661 double *tmp=new double[spaceDim];
7662 const int *nodal=_nodal_connec->getConstPointer();
7663 const int *nodalI=_nodal_connec_index->getConstPointer();
7664 const double *coor=_coords->getConstPointer();
7665 for(const int *w=begin;w!=end;w++)
7667 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7668 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7676 * 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".
7677 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7678 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7679 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7680 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7682 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7683 * \throw If spaceDim!=3 or meshDim!=2.
7684 * \throw If connectivity of \a this is invalid.
7685 * \throw If connectivity of a cell in \a this points to an invalid node.
7687 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7689 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7690 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7691 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7692 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7693 ret->alloc(nbOfCells,4);
7694 double *retPtr(ret->getPointer());
7695 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7696 const double *coor(_coords->begin());
7697 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7699 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7700 if(nodalI[1]-nodalI[0]>=3)
7702 for(int j=0;j<3;j++)
7704 int nodeId(nodal[nodalI[0]+1+j]);
7705 if(nodeId>=0 && nodeId<nbOfNodes)
7706 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7709 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7710 throw INTERP_KERNEL::Exception(oss.str().c_str());
7716 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7717 throw INTERP_KERNEL::Exception(oss.str().c_str());
7719 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7720 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7726 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7729 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7732 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7733 da->checkAllocated();
7734 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7736 int nbOfTuples=da->getNumberOfTuples();
7737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7739 c->alloc(2*nbOfTuples,1);
7740 cI->alloc(nbOfTuples+1,1);
7741 int *cp=c->getPointer();
7742 int *cip=cI->getPointer();
7744 for(int i=0;i<nbOfTuples;i++)
7746 *cp++=INTERP_KERNEL::NORM_POINT1;
7750 ret->setConnectivity(c,cI,true);
7754 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7755 * Cells and nodes of
7756 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7757 * \param [in] mesh1 - the first mesh.
7758 * \param [in] mesh2 - the second mesh.
7759 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7760 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7761 * is no more needed.
7762 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7763 * \throw If the coordinates array is not set in none of the meshes.
7764 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7765 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7767 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7769 std::vector<const MEDCouplingUMesh *> tmp(2);
7770 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7771 return MergeUMeshes(tmp);
7775 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7776 * Cells and nodes of
7777 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7778 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7779 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7780 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7781 * is no more needed.
7782 * \throw If \a a.size() == 0.
7783 * \throw If \a a[ *i* ] == NULL.
7784 * \throw If the coordinates array is not set in none of the meshes.
7785 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7786 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7788 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7790 std::size_t sz=a.size();
7792 return MergeUMeshesLL(a);
7793 for(std::size_t ii=0;ii<sz;ii++)
7796 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7797 throw INTERP_KERNEL::Exception(oss.str().c_str());
7799 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7800 std::vector< const MEDCouplingUMesh * > aa(sz);
7802 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7804 const MEDCouplingUMesh *cur=a[i];
7805 const DataArrayDouble *coo=cur->getCoords();
7807 spaceDim=coo->getNumberOfComponents();
7810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7811 for(std::size_t i=0;i<sz;i++)
7813 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7816 return MergeUMeshesLL(aa);
7821 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7825 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7826 int meshDim=(*it)->getMeshDimension();
7827 int nbOfCells=(*it)->getNumberOfCells();
7828 int meshLgth=(*it++)->getMeshLength();
7829 for(;it!=a.end();it++)
7831 if(meshDim!=(*it)->getMeshDimension())
7832 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7833 nbOfCells+=(*it)->getNumberOfCells();
7834 meshLgth+=(*it)->getMeshLength();
7836 std::vector<const MEDCouplingPointSet *> aps(a.size());
7837 std::copy(a.begin(),a.end(),aps.begin());
7838 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7839 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7840 ret->setCoords(pts);
7841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7842 c->alloc(meshLgth,1);
7843 int *cPtr=c->getPointer();
7844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7845 cI->alloc(nbOfCells+1,1);
7846 int *cIPtr=cI->getPointer();
7850 for(it=a.begin();it!=a.end();it++)
7852 int curNbOfCell=(*it)->getNumberOfCells();
7853 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7854 const int *curC=(*it)->_nodal_connec->getConstPointer();
7855 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7856 for(int j=0;j<curNbOfCell;j++)
7858 const int *src=curC+curCI[j];
7860 for(;src!=curC+curCI[j+1];src++,cPtr++)
7868 offset+=curCI[curNbOfCell];
7869 offset2+=(*it)->getNumberOfNodes();
7872 ret->setConnectivity(c,cI,true);
7879 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7880 * dimension and sharing the node coordinates array.
7881 * All cells of the first mesh precede all cells of the second mesh
7882 * within the result mesh.
7883 * \param [in] mesh1 - the first mesh.
7884 * \param [in] mesh2 - the second mesh.
7885 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7886 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7887 * is no more needed.
7888 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7889 * \throw If the meshes do not share the node coordinates array.
7890 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7891 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7893 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7895 std::vector<const MEDCouplingUMesh *> tmp(2);
7896 tmp[0]=mesh1; tmp[1]=mesh2;
7897 return MergeUMeshesOnSameCoords(tmp);
7901 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7902 * dimension and sharing the node coordinates array.
7903 * All cells of the *i*-th mesh precede all cells of the
7904 * (*i*+1)-th mesh within the result mesh.
7905 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7906 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7907 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7908 * is no more needed.
7909 * \throw If \a a.size() == 0.
7910 * \throw If \a a[ *i* ] == NULL.
7911 * \throw If the meshes do not share the node coordinates array.
7912 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7913 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7915 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7918 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7919 for(std::size_t ii=0;ii<meshes.size();ii++)
7922 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7923 throw INTERP_KERNEL::Exception(oss.str().c_str());
7925 const DataArrayDouble *coords=meshes.front()->getCoords();
7926 int meshDim=meshes.front()->getMeshDimension();
7927 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7929 int meshIndexLgth=0;
7930 for(;iter!=meshes.end();iter++)
7932 if(coords!=(*iter)->getCoords())
7933 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7934 if(meshDim!=(*iter)->getMeshDimension())
7935 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7936 meshLgth+=(*iter)->getMeshLength();
7937 meshIndexLgth+=(*iter)->getNumberOfCells();
7939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7940 nodal->alloc(meshLgth,1);
7941 int *nodalPtr=nodal->getPointer();
7942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7943 nodalIndex->alloc(meshIndexLgth+1,1);
7944 int *nodalIndexPtr=nodalIndex->getPointer();
7946 for(iter=meshes.begin();iter!=meshes.end();iter++)
7948 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7949 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7950 int nbOfCells=(*iter)->getNumberOfCells();
7951 int meshLgth2=(*iter)->getMeshLength();
7952 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7953 if(iter!=meshes.begin())
7954 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7956 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7959 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7960 ret->setName("merge");
7961 ret->setMeshDimension(meshDim);
7962 ret->setConnectivity(nodal,nodalIndex,true);
7963 ret->setCoords(coords);
7968 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7969 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7970 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7971 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7972 * New" mode are returned for each input mesh.
7973 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7974 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7975 * valid values [0,1,2], see zipConnectivityTraducer().
7976 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7977 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7978 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7980 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7981 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7982 * is no more needed.
7983 * \throw If \a meshes.size() == 0.
7984 * \throw If \a meshes[ *i* ] == NULL.
7985 * \throw If the meshes do not share the node coordinates array.
7986 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7987 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7988 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7989 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7991 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7993 //All checks are delegated to MergeUMeshesOnSameCoords
7994 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7995 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7996 corr.resize(meshes.size());
7997 std::size_t nbOfMeshes=meshes.size();
7999 const int *o2nPtr=o2n->getConstPointer();
8000 for(std::size_t i=0;i<nbOfMeshes;i++)
8002 DataArrayInt *tmp=DataArrayInt::New();
8003 int curNbOfCells=meshes[i]->getNumberOfCells();
8004 tmp->alloc(curNbOfCells,1);
8005 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8006 offset+=curNbOfCells;
8007 tmp->setName(meshes[i]->getName());
8014 * Makes all given meshes share the nodal connectivity array. The common connectivity
8015 * array is created by concatenating the connectivity arrays of all given meshes. All
8016 * the given meshes must be of the same space dimension but dimension of cells **can
8017 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8018 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8019 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8020 * \param [in,out] meshes - a vector of meshes to update.
8021 * \throw If any of \a meshes is NULL.
8022 * \throw If the coordinates array is not set in any of \a meshes.
8023 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8024 * \throw If \a meshes are of different space dimension.
8026 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8028 std::size_t sz=meshes.size();
8031 std::vector< const DataArrayDouble * > coords(meshes.size());
8032 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8033 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8037 (*it)->checkConnectivityFullyDefined();
8038 const DataArrayDouble *coo=(*it)->getCoords();
8043 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8044 oss << " has no coordinate array defined !";
8045 throw INTERP_KERNEL::Exception(oss.str().c_str());
8050 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8051 oss << " is null !";
8052 throw INTERP_KERNEL::Exception(oss.str().c_str());
8055 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8056 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8057 int offset=(*it)->getNumberOfNodes();
8058 (*it++)->setCoords(res);
8059 for(;it!=meshes.end();it++)
8061 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8062 (*it)->setCoords(res);
8063 (*it)->shiftNodeNumbersInConn(offset);
8064 offset+=oldNumberOfNodes;
8069 * Merges nodes coincident with a given precision within all given meshes that share
8070 * the nodal connectivity array. The given meshes **can be of different** mesh
8071 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8072 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8073 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8074 * \param [in,out] meshes - a vector of meshes to update.
8075 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8076 * \throw If any of \a meshes is NULL.
8077 * \throw If the \a meshes do not share the same node coordinates array.
8078 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8080 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8084 std::set<const DataArrayDouble *> s;
8085 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8088 s.insert((*it)->getCoords());
8091 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 !";
8092 throw INTERP_KERNEL::Exception(oss.str().c_str());
8097 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 !";
8098 throw INTERP_KERNEL::Exception(oss.str().c_str());
8100 const DataArrayDouble *coo=*(s.begin());
8104 DataArrayInt *comm,*commI;
8105 coo->findCommonTuples(eps,-1,comm,commI);
8106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8107 int oldNbOfNodes=coo->getNumberOfTuples();
8109 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8110 if(oldNbOfNodes==newNbOfNodes)
8112 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8113 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8115 (*it)->renumberNodesInConn(o2n->getConstPointer());
8116 (*it)->setCoords(newCoords);
8121 * 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.
8122 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8123 * \param isQuad specifies the policy of connectivity.
8124 * @ret in/out parameter in which the result will be append
8126 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8128 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8129 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8130 ret.push_back(cm.getExtrudedType());
8131 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8134 case INTERP_KERNEL::NORM_POINT1:
8136 ret.push_back(connBg[1]);
8137 ret.push_back(connBg[1]+nbOfNodesPerLev);
8140 case INTERP_KERNEL::NORM_SEG2:
8142 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8143 ret.insert(ret.end(),conn,conn+4);
8146 case INTERP_KERNEL::NORM_SEG3:
8148 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8149 ret.insert(ret.end(),conn,conn+8);
8152 case INTERP_KERNEL::NORM_QUAD4:
8154 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8155 ret.insert(ret.end(),conn,conn+8);
8158 case INTERP_KERNEL::NORM_TRI3:
8160 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8161 ret.insert(ret.end(),conn,conn+6);
8164 case INTERP_KERNEL::NORM_TRI6:
8166 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,
8167 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8168 ret.insert(ret.end(),conn,conn+15);
8171 case INTERP_KERNEL::NORM_QUAD8:
8174 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8175 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8176 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8178 ret.insert(ret.end(),conn,conn+20);
8181 case INTERP_KERNEL::NORM_POLYGON:
8183 std::back_insert_iterator< std::vector<int> > ii(ret);
8184 std::copy(connBg+1,connEnd,ii);
8186 std::reverse_iterator<const int *> rConnBg(connEnd);
8187 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8188 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8189 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8190 for(std::size_t i=0;i<nbOfRadFaces;i++)
8193 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8194 std::copy(conn,conn+4,ii);
8199 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8204 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8206 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8209 double v[3]={0.,0.,0.};
8210 std::size_t sz=std::distance(begin,end);
8215 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];
8216 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8217 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8219 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8221 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8222 // SEG3 forming a circle):
8223 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8225 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8226 for(std::size_t j=0;j<sz;j++)
8228 if (j%2) // current point i is quadratic, next point i+1 is standard
8231 ip1 = (j+1)%sz; // ip1 = "i+1"
8233 else // current point i is standard, next point i+1 is quadratic
8238 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8239 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8240 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8242 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8248 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8250 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8252 std::vector<std::pair<int,int> > edges;
8253 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8254 const int *bgFace=begin;
8255 for(std::size_t i=0;i<nbOfFaces;i++)
8257 const int *endFace=std::find(bgFace+1,end,-1);
8258 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8259 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8261 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8262 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8264 edges.push_back(p1);
8268 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8272 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8274 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8276 double vec0[3],vec1[3];
8277 std::size_t sz=std::distance(begin,end);
8279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8280 int nbOfNodes=(int)sz/2;
8281 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8282 const double *pt0=coords+3*begin[0];
8283 const double *pt1=coords+3*begin[nbOfNodes];
8284 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8285 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8288 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8290 std::size_t sz=std::distance(begin,end);
8291 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8292 std::size_t nbOfNodes(sz/2);
8293 std::copy(begin,end,(int *)tmp);
8294 for(std::size_t j=1;j<nbOfNodes;j++)
8296 begin[j]=tmp[nbOfNodes-j];
8297 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8301 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8303 std::size_t sz=std::distance(begin,end);
8305 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8306 double vec0[3],vec1[3];
8307 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8308 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];
8309 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;
8312 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8314 std::size_t sz=std::distance(begin,end);
8316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8318 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8319 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8320 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8324 * 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 )
8325 * 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
8328 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8329 * \param [in] coords the coordinates with nb of components exactly equal to 3
8330 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8331 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8332 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8334 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8336 int nbFaces=std::count(begin+1,end,-1)+1;
8337 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8338 double *vPtr=v->getPointer();
8339 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8340 double *pPtr=p->getPointer();
8341 const int *stFaceConn=begin+1;
8342 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8344 const int *endFaceConn=std::find(stFaceConn,end,-1);
8345 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8346 stFaceConn=endFaceConn+1;
8348 pPtr=p->getPointer(); vPtr=v->getPointer();
8349 DataArrayInt *comm1=0,*commI1=0;
8350 v->findCommonTuples(eps,-1,comm1,commI1);
8351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8352 const int *comm1Ptr=comm1->getConstPointer();
8353 const int *commI1Ptr=commI1->getConstPointer();
8354 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8355 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8357 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8358 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8359 mm->finishInsertingCells();
8361 for(int i=0;i<nbOfGrps1;i++)
8363 int vecId=comm1Ptr[commI1Ptr[i]];
8364 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8365 DataArrayInt *comm2=0,*commI2=0;
8366 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8367 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8368 const int *comm2Ptr=comm2->getConstPointer();
8369 const int *commI2Ptr=commI2->getConstPointer();
8370 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8371 for(int j=0;j<nbOfGrps2;j++)
8373 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8375 res->insertAtTheEnd(begin,end);
8376 res->pushBackSilent(-1);
8380 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8382 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8383 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8384 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8385 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8388 const int *idsNodePtr=idsNode->getConstPointer();
8389 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];
8390 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8391 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8392 if(std::abs(norm)>eps)
8394 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8395 mm3->rotate(center,vec,angle);
8397 mm3->changeSpaceDimension(2);
8398 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8399 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8400 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8401 int nbOfCells=mm4->getNumberOfCells();
8402 for(int k=0;k<nbOfCells;k++)
8405 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8406 res->pushBackSilent(idsNodePtr[*work]);
8407 res->pushBackSilent(-1);
8412 res->popBackSilent();
8416 * 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
8417 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8419 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8420 * \param [in] coords coordinates expected to have 3 components.
8421 * \param [in] begin start of the nodal connectivity of the face.
8422 * \param [in] end end of the nodal connectivity (excluded) of the face.
8423 * \param [out] v the normalized vector of size 3
8424 * \param [out] p the pos of plane
8426 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8428 std::size_t nbPoints=std::distance(begin,end);
8430 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8431 double vec[3]={0.,0.,0.};
8433 bool refFound=false;
8434 for(;j<nbPoints-1 && !refFound;j++)
8436 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8437 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8438 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8439 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8443 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8446 for(std::size_t i=j;i<nbPoints-1;i++)
8449 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8450 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8451 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8452 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8455 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8456 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];
8457 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8460 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8461 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8465 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8469 * This method tries to obtain a well oriented polyhedron.
8470 * If the algorithm fails, an exception will be thrown.
8472 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8474 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8475 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8476 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8478 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8479 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8480 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8482 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8485 std::size_t smthChanged=0;
8486 for(std::size_t i=0;i<nbOfFaces;i++)
8488 endFace=std::find(bgFace+1,end,-1);
8489 nbOfEdgesInFace=std::distance(bgFace,endFace);
8493 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8495 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8496 std::pair<int,int> p2(p1.second,p1.first);
8497 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8498 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8499 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8504 std::reverse(bgFace+1,endFace);
8505 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8507 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8508 std::pair<int,int> p2(p1.second,p1.first);
8509 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8510 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8511 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8512 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8513 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8514 if(it!=edgesOK.end())
8517 edgesFinished.push_back(p1);
8520 edgesOK.push_back(p1);
8527 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8529 if(!edgesOK.empty())
8530 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8531 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8532 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8534 for(std::size_t i=0;i<nbOfFaces;i++)
8536 endFace=std::find(bgFace+1,end,-1);
8537 std::reverse(bgFace+1,endFace);
8543 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8545 int nbOfNodesExpected(skin->getNumberOfNodes());
8546 const int *n2oPtr(n2o->getConstPointer());
8547 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8548 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8549 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8550 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8551 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8553 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8554 if(nbOfNodesExpected<1)
8556 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8557 *work++=n2oPtr[prevNode];
8558 for(int i=1;i<nbOfNodesExpected;i++)
8560 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8562 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8563 conn.erase(prevNode);
8566 int curNode(*(conn.begin()));
8567 *work++=n2oPtr[curNode];
8568 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8569 shar.erase(prevCell);
8572 prevCell=*(shar.begin());
8576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8587 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8589 int nbOfNodesExpected(skin->getNumberOfNodes());
8590 int nbOfTurn(nbOfNodesExpected/2);
8591 const int *n2oPtr(n2o->getConstPointer());
8592 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8593 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8594 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8595 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8596 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8597 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8598 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8599 if(nbOfNodesExpected<1)
8601 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8602 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8603 for(int i=1;i<nbOfTurn;i++)
8605 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8607 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8608 conn.erase(prevNode);
8611 int curNode(*(conn.begin()));
8612 *work=n2oPtr[curNode];
8613 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8614 shar.erase(prevCell);
8617 int curCell(*(shar.begin()));
8618 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8624 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8636 * This method makes the assumption spacedimension == meshdimension == 2.
8637 * This method works only for linear cells.
8639 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8641 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8643 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8645 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8646 int oldNbOfNodes(skin->getNumberOfNodes());
8647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8648 int nbOfNodesExpected(skin->getNumberOfNodes());
8649 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8650 int nbCells(skin->getNumberOfCells());
8651 if(nbCells==nbOfNodesExpected)
8652 return buildUnionOf2DMeshLinear(skin,n2o);
8653 else if(2*nbCells==nbOfNodesExpected)
8654 return buildUnionOf2DMeshQuadratic(skin,n2o);
8656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8660 * This method makes the assumption spacedimension == meshdimension == 3.
8661 * This method works only for linear cells.
8663 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8665 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8667 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8668 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8669 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8670 const int *conn=m->getNodalConnectivity()->getConstPointer();
8671 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8672 int nbOfCells=m->getNumberOfCells();
8673 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8674 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8677 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8678 for(int i=1;i<nbOfCells;i++)
8681 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8687 * \brief Creates a graph of cell neighbors
8688 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8689 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8691 * - index: 0 3 5 6 6
8692 * - value: 1 2 3 2 3 3
8693 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8694 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8696 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8698 checkConnectivityFullyDefined();
8700 int meshDim = this->getMeshDimension();
8701 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8702 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8703 this->getReverseNodalConnectivity(revConn,indexr);
8704 const int* indexr_ptr=indexr->getConstPointer();
8705 const int* revConn_ptr=revConn->getConstPointer();
8707 const ParaMEDMEM::DataArrayInt* index;
8708 const ParaMEDMEM::DataArrayInt* conn;
8709 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8710 index=this->getNodalConnectivityIndex();
8711 int nbCells=this->getNumberOfCells();
8712 const int* index_ptr=index->getConstPointer();
8713 const int* conn_ptr=conn->getConstPointer();
8715 //creating graph arcs (cell to cell relations)
8716 //arcs are stored in terms of (index,value) notation
8719 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8720 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8722 //warning here one node have less than or equal effective number of cell with it
8723 //but cell could have more than effective nodes
8724 //because other equals nodes in other domain (with other global inode)
8725 std::vector <int> cell2cell_index(nbCells+1,0);
8726 std::vector <int> cell2cell;
8727 cell2cell.reserve(3*nbCells);
8729 for (int icell=0; icell<nbCells;icell++)
8731 std::map<int,int > counter;
8732 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8734 int inode=conn_ptr[iconn];
8735 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8737 int icell2=revConn_ptr[iconnr];
8738 std::map<int,int>::iterator iter=counter.find(icell2);
8739 if (iter!=counter.end()) (iter->second)++;
8740 else counter.insert(std::make_pair(icell2,1));
8743 for (std::map<int,int>::const_iterator iter=counter.begin();
8744 iter!=counter.end(); iter++)
8745 if (iter->second >= meshDim)
8747 cell2cell_index[icell+1]++;
8748 cell2cell.push_back(iter->first);
8753 cell2cell_index[0]=0;
8754 for (int icell=0; icell<nbCells;icell++)
8755 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8757 //filling up index and value to create skylinearray structure
8758 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8763 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8764 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8766 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8770 for(int i=0;i<nbOfNodesInCell;i++)
8771 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8772 else if(spaceDim==2)
8774 for(int i=0;i<nbOfNodesInCell;i++)
8776 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8784 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8786 int nbOfCells=getNumberOfCells();
8788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8789 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};
8790 ofs << " <" << getVTKDataSetType() << ">\n";
8791 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8792 ofs << " <PointData>\n" << pointData << std::endl;
8793 ofs << " </PointData>\n";
8794 ofs << " <CellData>\n" << cellData << std::endl;
8795 ofs << " </CellData>\n";
8796 ofs << " <Points>\n";
8797 if(getSpaceDimension()==3)
8798 _coords->writeVTK(ofs,8,"Points",byteData);
8801 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8802 coo->writeVTK(ofs,8,"Points",byteData);
8804 ofs << " </Points>\n";
8805 ofs << " <Cells>\n";
8806 const int *cPtr=_nodal_connec->getConstPointer();
8807 const int *cIPtr=_nodal_connec_index->getConstPointer();
8808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8812 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8813 int szFaceOffsets=0,szConn=0;
8814 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8817 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8820 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8821 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8825 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8826 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8827 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8828 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8829 w4=std::copy(c.begin(),c.end(),w4);
8832 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8833 types->writeVTK(ofs,8,"UInt8","types",byteData);
8834 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8835 if(szFaceOffsets!=0)
8836 {//presence of Polyhedra
8837 connectivity->reAlloc(szConn);
8838 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8840 w1=faces->getPointer();
8841 for(int i=0;i<nbOfCells;i++)
8842 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8844 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8846 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8847 for(int j=0;j<nbFaces;j++)
8849 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8850 *w1++=(int)std::distance(w6,w5);
8851 w1=std::copy(w6,w5,w1);
8855 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8857 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8858 ofs << " </Cells>\n";
8859 ofs << " </Piece>\n";
8860 ofs << " </" << getVTKDataSetType() << ">\n";
8863 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8865 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8867 { stream << " Not set !"; return ; }
8868 stream << " Mesh dimension : " << _mesh_dim << ".";
8872 { stream << " No coordinates set !"; return ; }
8873 if(!_coords->isAllocated())
8874 { stream << " Coordinates set but not allocated !"; return ; }
8875 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8876 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8877 if(!_nodal_connec_index)
8878 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8879 if(!_nodal_connec_index->isAllocated())
8880 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8881 int lgth=_nodal_connec_index->getNumberOfTuples();
8882 int cpt=_nodal_connec_index->getNumberOfComponents();
8883 if(cpt!=1 || lgth<1)
8885 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8888 std::string MEDCouplingUMesh::getVTKDataSetType() const
8890 return std::string("UnstructuredGrid");
8893 std::string MEDCouplingUMesh::getVTKFileExtension() const
8895 return std::string("vtu");
8899 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8900 * returns a result mesh constituted by polygons.
8901 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8902 * all nodes from m2.
8903 * The meshes should be in 2D space. In
8904 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8906 * \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
8907 * 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)
8908 * \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
8909 * 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)
8910 * \param [in] eps - precision used to detect coincident mesh entities.
8911 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8912 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8913 * this array using decrRef() as it is no more needed.
8914 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8915 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8916 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8917 * any cell of \a m2. The caller is to delete this array using decrRef() as
8918 * it is no more needed.
8919 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8920 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8921 * is no more needed.
8922 * \throw If the coordinates array is not set in any of the meshes.
8923 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8924 * \throw If any of the meshes is not a 2D mesh in 2D space.
8926 * \sa conformize2D, mergeNodes
8928 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8929 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8933 m1->checkFullyDefined();
8934 m2->checkFullyDefined();
8935 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8938 // Step 1: compute all edge intersections (new nodes)
8939 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8940 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8941 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8942 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8943 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8944 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8945 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8946 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8948 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8950 // Step 2: re-order newly created nodes according to the ordering found in m2
8951 std::vector< std::vector<int> > intersectEdge2;
8952 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8953 subDiv2.clear(); dd5=0; dd6=0;
8956 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8957 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8958 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8959 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8961 // Step 4: Prepare final result:
8962 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8963 addCooDa->alloc((int)(addCoo.size())/2,2);
8964 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8965 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8966 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8967 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8968 std::vector<const DataArrayDouble *> coordss(4);
8969 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8970 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8971 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8973 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8976 ret->setConnectivity(conn,connI,true);
8977 ret->setCoords(coo);
8978 cellNb1=c1.retn(); cellNb2=c2.retn();
8984 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8986 if(candidates.empty())
8988 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8990 const std::vector<int>& pool(intersectEdge1[*it]);
8991 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8992 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8997 tmp[0]=stop; tmp[1]=start;
8998 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9007 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,
9008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9010 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9011 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9012 int nCells(mesh1D->getNumberOfCells());
9013 if(nCells!=(int)intersectEdge2.size())
9014 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9015 const DataArrayDouble *coo2(mesh1D->getCoords());
9016 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9017 const double *coo2Ptr(coo2->begin());
9018 int offset1(coords1->getNumberOfTuples());
9019 int offset2(offset1+coo2->getNumberOfTuples());
9020 int offset3(offset2+addCoo.size()/2);
9021 std::vector<double> addCooQuad;
9022 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9023 int tmp[4],cicnt(0),kk(0);
9024 for(int i=0;i<nCells;i++)
9026 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9027 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9028 const std::vector<int>& subEdges(intersectEdge2[i]);
9029 int nbSubEdge(subEdges.size()/2);
9030 for(int j=0;j<nbSubEdge;j++,kk++)
9032 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));
9033 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9034 INTERP_KERNEL::Edge *e2Ptr(e2);
9035 std::map<int,int>::const_iterator itm;
9036 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9038 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9039 itm=mergedNodes.find(subEdges[2*j]);
9040 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9041 itm=mergedNodes.find(subEdges[2*j+1]);
9042 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9043 tmp[3]=offset3+(int)addCooQuad.size()/2;
9045 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9047 cOut->insertAtTheEnd(tmp,tmp+4);
9048 ciOut->pushBackSilent(cicnt);
9052 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9053 itm=mergedNodes.find(subEdges[2*j]);
9054 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9055 itm=mergedNodes.find(subEdges[2*j+1]);
9056 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9058 cOut->insertAtTheEnd(tmp,tmp+3);
9059 ciOut->pushBackSilent(cicnt);
9062 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9064 idsInRetColinear->pushBackSilent(kk);
9065 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9070 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9071 ret->setConnectivity(cOut,ciOut,true);
9072 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9073 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9074 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9075 std::vector<const DataArrayDouble *> coordss(4);
9076 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9077 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9078 ret->setCoords(arr);
9082 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9084 std::vector<int> allEdges;
9085 for(const int *it2(descBg);it2!=descEnd;it2++)
9087 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9089 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9091 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9093 std::size_t nb(allEdges.size());
9095 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9096 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9097 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9098 ret->setCoords(coords);
9099 ret->allocateCells(1);
9100 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9101 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9102 connOut[kk]=allEdges[2*kk];
9103 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9107 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9109 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9110 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9112 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9113 if(sz!=std::distance(descBg,descEnd))
9114 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9115 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9116 std::vector<int> allEdges,centers;
9117 const double *coordsPtr(coords->begin());
9118 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9119 int offset(coords->getNumberOfTuples());
9120 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9122 INTERP_KERNEL::NormalizedCellType typeOfSon;
9123 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9124 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9126 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9128 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9130 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9132 {//the current edge has been subsplit -> create corresponding centers.
9133 std::size_t nbOfCentersToAppend(edge1.size()/2);
9134 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9135 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9136 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9137 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9140 const double *aa(coordsPtr+2*(*it3++));
9141 const double *bb(coordsPtr+2*(*it3++));
9142 ee->getMiddleOfPoints(aa,bb,tmpp);
9143 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9144 centers.push_back(offset+k);
9148 std::size_t nb(allEdges.size());
9150 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9151 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9152 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9154 ret->setCoords(coords);
9157 addCoo->rearrange(2);
9158 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9159 ret->setCoords(addCoo);
9161 ret->allocateCells(1);
9162 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9163 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9164 connOut[kk]=allEdges[2*kk];
9165 connOut.insert(connOut.end(),centers.begin(),centers.end());
9166 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9171 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9174 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9176 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9178 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9179 if(!cm.isQuadratic())
9180 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9182 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9185 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9188 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9190 const INTERP_KERNEL::Edge *ee(*it);
9191 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9195 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9198 const double *coo(mesh2D->getCoords()->begin());
9199 std::size_t sz(conn.size());
9200 std::vector<double> addCoo;
9201 std::vector<int> conn2(conn);
9202 int offset(mesh2D->getNumberOfNodes());
9203 for(std::size_t i=0;i<sz;i++)
9206 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9207 addCoo.insert(addCoo.end(),tmp,tmp+2);
9208 conn2.push_back(offset+(int)i);
9210 mesh2D->getCoords()->rearrange(1);
9211 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9212 mesh2D->getCoords()->rearrange(2);
9213 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9218 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9220 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9221 * a set of edges defined in \a splitMesh1D.
9223 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9224 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9226 std::size_t nb(edge1Bis.size()/2);
9227 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9228 int iEnd(splitMesh1D->getNumberOfCells());
9230 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9232 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9233 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9234 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9237 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9238 out0.resize(1); out1.resize(1);
9239 std::vector<int>& connOut(out0[0]);
9240 connOut.resize(nbOfEdgesOf2DCellSplit);
9241 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9242 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9243 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9245 connOut[kk]=edge1Bis[2*kk];
9246 edgesPtr[kk]=edge1BisPtr[2*kk];
9251 // [i,iEnd[ contains the
9252 out0.resize(2); out1.resize(2);
9253 std::vector<int>& connOutLeft(out0[0]);
9254 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9255 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9256 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9257 for(std::size_t k=ii;k<jj+1;k++)
9258 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9259 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9260 for(int ik=0;ik<iEnd;ik++)
9262 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9263 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9266 for(int ik=iEnd-1;ik>=0;ik--)
9267 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9268 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9269 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9270 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9271 for(int ik=0;ik<iEnd;ik++)
9272 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9273 eright.insert(eright.end(),ees.begin(),ees.end());
9285 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9287 std::vector<int> _edges;
9288 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9291 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9293 std::size_t nbe(edges.size());
9294 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9295 for(std::size_t i=0;i<nbe;i++)
9297 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9298 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9300 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9301 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9302 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9308 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9309 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9310 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9311 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9312 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9316 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9317 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9322 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9324 const MEDCouplingUMesh *mesh(_mesh);
9330 { _left++; _right++; return ; }
9333 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9334 if((isLeft && isRight) || (!isLeft && !isRight))
9335 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9346 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9347 if((isLeft && isRight) || (!isLeft && !isRight))
9348 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9363 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9365 const MEDCouplingUMesh *mesh(_mesh);
9368 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9371 {// not fully splitting cell case
9372 if(mesh2D->getNumberOfCells()==1)
9373 {//little optimization. 1 cell no need to find in which cell mesh is !
9374 neighbors[0]=offset; neighbors[1]=offset;
9379 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9380 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9382 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9383 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9388 class VectorOfCellInfo
9391 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9392 std::size_t size() const { return _pool.size(); }
9393 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9394 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);
9395 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9396 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9397 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9398 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9400 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9401 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9402 const CellInfo& get(int pos) const;
9403 CellInfo& get(int pos);
9405 std::vector<CellInfo> _pool;
9406 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9407 std::vector<EdgeInfo> _edge_info;
9410 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9412 _pool[0]._edges=edges;
9413 _pool[0]._edges_ptr=edgesPtr;
9416 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9419 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9422 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9424 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9425 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9426 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9429 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)
9431 get(pos);//to check pos
9432 bool isFast(pos==0 && _pool.size()==1);
9433 std::size_t sz(edges.size());
9434 // dealing with edges
9436 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9438 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9440 std::vector<CellInfo> pool(_pool.size()-1+sz);
9441 for(int i=0;i<pos;i++)
9443 for(std::size_t j=0;j<sz;j++)
9444 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9445 for(int i=pos+1;i<(int)_pool.size();i++)
9446 pool[i+sz-1]=_pool[i];
9450 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9458 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9465 if(pos<_ze_mesh->getNumberOfCells()-1)
9467 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9470 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9471 for(std::size_t j=0;j<ms2.size();j++)
9473 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9476 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9478 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9481 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9484 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9486 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9488 if((*it).isInMyRange(pos))
9491 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9494 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9496 get(pos);//to check;
9497 if(_edge_info.empty())
9499 std::size_t sz(_edge_info.size()-1);
9500 for(std::size_t i=0;i<sz;i++)
9501 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9504 const CellInfo& VectorOfCellInfo::get(int pos) const
9506 if(pos<0 || pos>=(int)_pool.size())
9507 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9511 CellInfo& VectorOfCellInfo::get(int pos)
9513 if(pos<0 || pos>=(int)_pool.size())
9514 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9520 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9521 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9523 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9525 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9527 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9529 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9532 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9533 if(nbCellsInSplitMesh1D==0)
9534 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9535 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9536 std::size_t nb(allEdges.size()),jj;
9538 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9539 std::vector<int> edge1Bis(nb*2);
9540 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9541 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9542 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9543 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9544 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9546 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9547 int *idsLeftRightPtr(idsLeftRight->getPointer());
9548 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9549 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9550 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9552 for(;iEnd<nbCellsInSplitMesh1D;)
9554 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9560 if(iEnd<nbCellsInSplitMesh1D)
9563 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9564 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9566 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9567 retTmp->setCoords(splitMesh1D->getCoords());
9568 retTmp->allocateCells();
9570 std::vector< std::vector<int> > out0;
9571 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9573 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9574 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9575 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9576 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9580 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9581 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9582 return pool.getZeMesh().retn();
9585 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9586 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9587 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9589 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9591 std::vector<int> allEdges;
9592 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9593 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9595 int edgeId(std::abs(*it)-1);
9596 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9597 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9598 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9600 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9602 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9603 std::size_t sz(edge1.size());
9604 for(std::size_t cnt=0;cnt<sz;cnt++)
9605 allEdgesPtr.push_back(ee);
9608 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9611 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9613 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9614 {//easy case comparison not
9615 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9617 else if(typ1.isQuadratic() && typ2.isQuadratic())
9619 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9622 if(conn1[2]==conn2[2])
9624 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9625 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9629 {//only one is quadratic
9630 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9633 const double *a(0),*bb(0),*be(0);
9634 if(typ1.isQuadratic())
9636 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9640 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9642 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9643 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9649 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9650 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9652 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9654 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9656 if(candidatesIn2DEnd==candidatesIn2DBg)
9657 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9658 const double *coo(mesh2DSplit->getCoords()->begin());
9659 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9660 return *candidatesIn2DBg;
9661 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9663 if(cellIdInMesh1DSplitRelative<0)
9664 cur1D->changeOrientationOfCells();
9665 const int *c1D(cur1D->getNodalConnectivity()->begin());
9666 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9667 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9669 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9670 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9671 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9672 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9673 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9674 for(unsigned it2=0;it2<sz;it2++)
9676 INTERP_KERNEL::NormalizedCellType typeOfSon;
9677 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9678 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9679 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9683 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9689 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9690 * 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
9691 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9692 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9694 * \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
9695 * 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)
9696 * \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
9697 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9698 * \param [in] eps - precision used to perform intersections and localization operations.
9699 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9700 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9701 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9702 * 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.
9703 * \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
9704 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9705 * 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.
9707 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9709 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9711 if(!mesh2D || !mesh1D)
9712 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9713 mesh2D->checkFullyDefined();
9714 mesh1D->checkFullyDefined();
9715 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9716 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9717 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9718 // Step 1: compute all edge intersections (new nodes)
9719 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9720 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9721 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9722 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9724 // Build desc connectivity
9725 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9726 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9727 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9728 std::map<int,int> mergedNodes;
9729 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9730 // use mergeNodes to fix intersectEdge1
9731 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9733 std::size_t n((*it0).size()/2);
9734 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9735 std::map<int,int>::const_iterator it1;
9736 it1=mergedNodes.find(eltStart);
9737 if(it1!=mergedNodes.end())
9738 (*it0)[0]=(*it1).second;
9739 it1=mergedNodes.find(eltEnd);
9740 if(it1!=mergedNodes.end())
9741 (*it0)[2*n-1]=(*it1).second;
9744 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9745 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9746 // Step 2: re-order newly created nodes according to the ordering found in m2
9747 std::vector< std::vector<int> > intersectEdge2;
9748 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9750 // Step 3: compute splitMesh1D
9751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9753 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9754 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9757 // deal with cells in mesh2D that are not cut but only some of their edges are
9758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9759 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9760 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9761 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
9762 if(!idsInDesc2DToBeRefined->empty())
9764 DataArrayInt *out0(0),*outi0(0);
9765 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9768 out0s=out0s->buildUnique();
9772 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9773 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9775 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9778 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9779 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9780 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9781 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9782 if((DataArrayInt *)out0s)
9783 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9784 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9785 // OK all is ready to insert in ret2 mesh
9786 if(!untouchedCells->empty())
9787 {// the most easy part, cells in mesh2D not impacted at all
9788 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9789 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9790 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9792 if((DataArrayInt *)out0s)
9793 {// here dealing with cells in out0s but not in cellsToBeModified
9794 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9795 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9796 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9798 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9799 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9801 int offset(ret2->getNumberOfTuples());
9802 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9804 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9805 int kk(0),*ret3ptr(partOfRet3->getPointer());
9806 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9808 int faceId(std::abs(*it)-1);
9809 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9811 int tmp(fewModifiedCells->locateValue(*it2));
9814 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9815 ret3ptr[2*kk]=tmp+offset;
9816 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9817 ret3ptr[2*kk+1]=tmp+offset;
9820 {//the current edge is shared by a 2D cell that will be split just after
9821 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9822 ret3ptr[2*kk]=-(*it2+1);
9823 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9824 ret3ptr[2*kk+1]=-(*it2+1);
9828 m1Desc->setCoords(ret1->getCoords());
9829 ret1NonCol->setCoords(ret1->getCoords());
9830 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9831 if(!outMesh2DSplit.empty())
9833 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9834 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9835 (*itt)->setCoords(da);
9838 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9839 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9842 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9844 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9846 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));
9847 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9848 outMesh2DSplit.push_back(splitOfOneCell);
9849 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9850 ret2->pushBackSilent(*it);
9853 std::size_t nbOfMeshes(outMesh2DSplit.size());
9854 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9855 for(std::size_t i=0;i<nbOfMeshes;i++)
9856 tmp[i]=outMesh2DSplit[i];
9858 ret1->getCoords()->setInfoOnComponents(compNames);
9859 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9860 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9863 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9865 int old2DCellId(-ret3->getIJ(*it,0)-1);
9866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9867 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
9869 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9872 splitMesh1D=ret1.retn();
9873 splitMesh2D=ret2D.retn();
9874 cellIdInMesh2D=ret2.retn();
9875 cellIdInMesh1D=ret3.retn();
9879 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9880 * (newly created) nodes corresponding to the edge intersections.
9882 * @param[out] cr, crI connectivity of the resulting mesh
9883 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9884 * TODO: describe input parameters
9886 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9887 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9888 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9889 const std::vector<double>& addCoords,
9890 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9892 static const int SPACEDIM=2;
9893 const double *coo1(m1->getCoords()->getConstPointer());
9894 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9895 int offset1(m1->getNumberOfNodes());
9896 const double *coo2(m2->getCoords()->getConstPointer());
9897 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9898 int offset2(offset1+m2->getNumberOfNodes());
9899 int offset3(offset2+((int)addCoords.size())/2);
9900 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9901 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9902 // Here a BBTree on 2D-cells, not on segments:
9903 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9904 int ncell1(m1->getNumberOfCells());
9906 for(int i=0;i<ncell1;i++)
9908 std::vector<int> candidates2;
9909 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9910 std::map<INTERP_KERNEL::Node *,int> mapp;
9911 std::map<int,INTERP_KERNEL::Node *> mappRev;
9912 INTERP_KERNEL::QuadraticPolygon pol1;
9913 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9914 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9915 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9916 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9917 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9918 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9919 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9921 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
9922 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9923 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9924 for(it1.first();!it1.finished();it1.next())
9925 edges1.insert(it1.current()->getPtr());
9927 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9928 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9930 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9932 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9933 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9934 // Complete mapping with elements coming from the current cell it2 in mesh2:
9935 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9936 // pol2 is the new QP in the final merged result.
9937 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9938 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9941 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9943 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9944 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9945 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9946 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9948 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9949 // by m2 but that we still want to keep in the final result.
9954 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9956 catch(INTERP_KERNEL::Exception& e)
9958 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();
9959 throw INTERP_KERNEL::Exception(oss.str().c_str());
9962 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9963 (*it).second->decrRef();
9968 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9969 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9970 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9971 * The caller is to deal with the resulting DataArrayInt.
9972 * \throw If the coordinate array is not set.
9973 * \throw If the nodal connectivity of the cells is not defined.
9974 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9975 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9977 * \sa DataArrayInt::sortEachPairToMakeALinkedList
9979 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9981 checkFullyDefined();
9982 if(getMeshDimension()!=1)
9983 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9985 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9988 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9989 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9990 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9991 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9992 const int * dsi(_dsi->getConstPointer());
9993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9995 if (dsii->getNumberOfTuples())
9996 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9998 int nc(getNumberOfCells());
9999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10000 result->alloc(nc,1);
10002 // set of edges not used so far
10003 std::set<int> edgeSet;
10004 for (int i=0; i<nc; edgeSet.insert(i), i++);
10008 // while we have points with only one neighbor segments
10011 std::list<int> linePiece;
10012 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10013 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10015 // Fill the list forward (resp. backward) from the start segment:
10016 int activeSeg = startSeg;
10017 int prevPointId = -20;
10019 while (!edgeSet.empty())
10021 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10024 linePiece.push_back(activeSeg);
10026 linePiece.push_front(activeSeg);
10027 edgeSet.erase(activeSeg);
10030 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10031 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10032 if (dsi[ptId] == 1) // hitting the end of the line
10034 prevPointId = ptId;
10035 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10036 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10039 // Done, save final piece into DA:
10040 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10041 newIdx += linePiece.size();
10043 // identify next valid start segment (one which is not consumed)
10044 if(!edgeSet.empty())
10045 startSeg = *(edgeSet.begin());
10047 while (!edgeSet.empty());
10048 return result.retn();
10053 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10055 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10056 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10058 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10059 int v((*it).second);
10060 if(v==forbVal0 || v==forbVal1)
10062 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10063 isect.push_back(v);
10066 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10071 bool presenceOfOn(false);
10072 for(int i=0;i<sz;i++)
10074 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10075 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10077 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10078 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10080 return presenceOfOn;
10086 * 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.
10087 * 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.
10088 * 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.
10089 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10091 * \return int - the number of new nodes created (in most of cases 0).
10093 * \throw If \a this is not coherent.
10094 * \throw If \a this has not spaceDim equal to 2.
10095 * \throw If \a this has not meshDim equal to 2.
10096 * \throw If some subcells needed to be split are orphan.
10097 * \sa MEDCouplingUMesh::conformize2D
10099 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10101 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10102 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10103 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10104 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10105 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10106 if(midOpt==0 && midOptI==0)
10108 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10111 else if(midOpt!=0 && midOptI!=0)
10112 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10118 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10119 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10120 * 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
10121 * 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).
10122 * 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.
10124 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10125 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10127 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10128 * This method expects that all nodes in \a this are not closer than \a eps.
10129 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10131 * \param [in] eps the relative error to detect merged edges.
10132 * \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
10133 * that the user is expected to deal with.
10135 * \throw If \a this is not coherent.
10136 * \throw If \a this has not spaceDim equal to 2.
10137 * \throw If \a this has not meshDim equal to 2.
10138 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10140 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10142 static const int SPACEDIM=2;
10144 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10145 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10147 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10148 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10149 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10150 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10151 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10152 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10153 std::vector<double> addCoo;
10154 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10155 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10156 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10157 for(int i=0;i<nDescCell;i++)
10159 std::vector<int> candidates;
10160 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10161 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10164 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10165 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10166 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10167 INTERP_KERNEL::MergePoints merge;
10168 INTERP_KERNEL::QuadraticPolygon c1,c2;
10169 e1->intersectWith(e2,merge,c1,c2);
10170 e1->decrRef(); e2->decrRef();
10171 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10172 overlapEdge[i].push_back(*it);
10173 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10174 overlapEdge[*it].push_back(i);
10177 // splitting done. sort intersect point in intersectEdge.
10178 std::vector< std::vector<int> > middle(nDescCell);
10179 int nbOf2DCellsToBeSplit(0);
10180 bool middleNeedsToBeUsed(false);
10181 std::vector<bool> cells2DToTreat(nDescCell,false);
10182 for(int i=0;i<nDescCell;i++)
10184 std::vector<int>& isect(intersectEdge[i]);
10185 int sz((int)isect.size());
10188 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10189 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10190 e->sortSubNodesAbs(coords,isect);
10195 int idx0(rdi[i]),idx1(rdi[i+1]);
10197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10198 if(!cells2DToTreat[rd[idx0]])
10200 cells2DToTreat[rd[idx0]]=true;
10201 nbOf2DCellsToBeSplit++;
10203 // try to reuse at most eventual 'middle' of SEG3
10204 std::vector<int>& mid(middle[i]);
10205 mid.resize(sz+1,-1);
10206 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10208 middleNeedsToBeUsed=true;
10209 const std::vector<int>& candidates(overlapEdge[i]);
10210 std::vector<int> trueCandidates;
10211 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10212 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10213 trueCandidates.push_back(*itc);
10214 int stNode(c[ci[i]+1]),endNode(isect[0]);
10215 for(int j=0;j<sz+1;j++)
10217 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10219 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10220 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10221 { mid[j]=*itc; break; }
10224 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10229 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10230 if(nbOf2DCellsToBeSplit==0)
10233 int *retPtr(ret->getPointer());
10234 for(int i=0;i<nCell;i++)
10235 if(cells2DToTreat[i])
10238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10239 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10240 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10241 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10242 if(middleNeedsToBeUsed)
10243 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10244 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10245 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10246 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.
10247 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10249 bool areNodesMerged; int newNbOfNodes;
10250 if(nbOfNodesCreated!=0)
10251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10257 * 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.
10258 * 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).
10259 * 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
10260 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10261 * 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
10262 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10264 * 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
10265 * using new instance, idem for coordinates.
10267 * 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.
10269 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10271 * \throw If \a this is not coherent.
10272 * \throw If \a this has not spaceDim equal to 2.
10273 * \throw If \a this has not meshDim equal to 2.
10275 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10277 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10281 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10283 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10284 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10285 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10286 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10288 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10289 const double *coords(_coords->begin());
10290 int *newciptr(newci->getPointer());
10291 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10293 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10294 ret->pushBackSilent(i);
10295 newciptr[1]=newc->getNumberOfTuples();
10300 if(!appendedCoords->empty())
10302 appendedCoords->rearrange(2);
10303 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10305 setCoords(newCoords);
10308 setConnectivity(newc,newci,true);
10313 * \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.
10314 * 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.
10315 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10316 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10317 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10318 * \param [out] addCoo - nodes to be append at the end
10319 * \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.
10321 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10322 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)
10324 static const int SPACEDIM=2;
10325 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10326 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10327 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10328 // Build BB tree of all edges in the tool mesh (second mesh)
10329 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10330 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10331 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10332 intersectEdge1.resize(nDescCell1);
10333 colinear2.resize(nDescCell2);
10334 subDiv2.resize(nDescCell2);
10335 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10337 std::vector<int> candidates1(1);
10338 int offset1(m1Desc->getNumberOfNodes());
10339 int offset2(offset1+m2Desc->getNumberOfNodes());
10340 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10342 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10343 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10344 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10346 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10347 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10348 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10350 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10351 // 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
10352 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10353 std::set<INTERP_KERNEL::Node *> nodes;
10354 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10355 std::size_t szz(nodes.size());
10356 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10357 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10358 for(std::size_t iii=0;iii<szz;iii++,itt++)
10359 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10360 // end of protection
10361 // Performs egde cutting:
10362 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10367 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10368 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10373 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10374 * It builds the descending connectivity of the two meshes, and then using a binary tree
10375 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10376 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10378 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10379 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10380 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10381 std::vector<double>& addCoo,
10382 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10384 // Build desc connectivity
10385 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10386 desc2=DataArrayInt::New();
10387 descIndx2=DataArrayInt::New();
10388 revDesc2=DataArrayInt::New();
10389 revDescIndx2=DataArrayInt::New();
10390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10392 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10393 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10394 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10395 std::map<int,int> notUsedMap;
10396 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10397 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10398 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10402 * This method performs the 2nd step of Partition of 2D mesh.
10403 * This method has 4 inputs :
10404 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10405 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10406 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10407 * 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'
10408 * Nodes end up lying consecutively on a cutted edge.
10409 * \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.
10410 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10411 * \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.
10412 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10413 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10415 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10416 const std::vector<double>& addCoo,
10417 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10419 int offset1=m1->getNumberOfNodes();
10420 int ncell=m2->getNumberOfCells();
10421 const int *c=m2->getNodalConnectivity()->getConstPointer();
10422 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10423 const double *coo=m2->getCoords()->getConstPointer();
10424 const double *cooBis=m1->getCoords()->getConstPointer();
10425 int offset2=offset1+m2->getNumberOfNodes();
10426 intersectEdge.resize(ncell);
10427 for(int i=0;i<ncell;i++,cI++)
10429 const std::vector<int>& divs=subDiv[i];
10430 int nnode=cI[1]-cI[0]-1;
10431 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10432 std::map<INTERP_KERNEL::Node *, int> mapp22;
10433 for(int j=0;j<nnode;j++)
10435 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10436 int nnid=c[(*cI)+j+1];
10437 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10438 mapp22[nn]=nnid+offset1;
10440 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10441 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10442 ((*it).second.first)->decrRef();
10443 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10444 std::map<INTERP_KERNEL::Node *,int> mapp3;
10445 for(std::size_t j=0;j<divs.size();j++)
10448 INTERP_KERNEL::Node *tmp=0;
10450 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10451 else if(id<offset2)
10452 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10454 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10458 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10459 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10466 * 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).
10467 * 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
10468 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10469 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10470 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10471 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10472 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10473 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10474 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10475 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10476 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10477 * \param [out] cut3DSuf input/output param.
10479 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10480 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10481 const int *desc, const int *descIndx,
10482 std::vector< std::pair<int,int> >& cut3DSurf)
10484 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10485 int nbOf3DSurfCell=(int)cut3DSurf.size();
10486 for(int i=0;i<nbOf3DSurfCell;i++)
10488 std::vector<int> res;
10489 int offset=descIndx[i];
10490 int nbOfSeg=descIndx[i+1]-offset;
10491 for(int j=0;j<nbOfSeg;j++)
10493 int edgeId=desc[offset+j];
10494 int status=cut3DCurve[edgeId];
10498 res.push_back(status);
10501 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10502 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10510 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10516 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10517 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10520 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10524 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10529 {// case when plane is on a multi colinear edge of a polyhedron
10530 if((int)res.size()==2*nbOfSeg)
10532 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10535 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10542 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10543 * 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).
10544 * 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
10545 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10546 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10547 * \param desc is the descending connectivity 3D->3DSurf
10548 * \param descIndx is the descending connectivity index 3D->3DSurf
10550 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10551 const int *desc, const int *descIndx,
10552 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10554 checkFullyDefined();
10555 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10556 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10557 const int *nodal3D=_nodal_connec->getConstPointer();
10558 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10559 int nbOfCells=getNumberOfCells();
10560 for(int i=0;i<nbOfCells;i++)
10562 std::map<int, std::set<int> > m;
10563 int offset=descIndx[i];
10564 int nbOfFaces=descIndx[i+1]-offset;
10567 for(int j=0;j<nbOfFaces;j++)
10569 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10570 if(p.first!=-1 && p.second!=-1)
10574 start=p.first; end=p.second;
10575 m[p.first].insert(p.second);
10576 m[p.second].insert(p.first);
10580 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10581 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10582 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10583 INTERP_KERNEL::NormalizedCellType cmsId;
10584 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10585 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10586 for(unsigned k=0;k<nbOfNodesSon;k++)
10588 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10589 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10596 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10600 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10601 const std::set<int>& s=(*it).second;
10602 std::set<int> s2; s2.insert(prev);
10604 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10607 int val=*s3.begin();
10608 conn.push_back(start);
10615 conn.push_back(end);
10618 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10619 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10620 cellIds->pushBackSilent(i);
10626 * 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
10627 * 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
10628 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10629 * 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
10630 * 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.
10632 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10634 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10636 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10639 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10640 if(cm.getDimension()==2)
10642 const int *node=nodalConnBg+1;
10643 int startNode=*node++;
10644 double refX=coords[2*startNode];
10645 for(;node!=nodalConnEnd;node++)
10647 if(coords[2*(*node)]<refX)
10650 refX=coords[2*startNode];
10653 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10657 double angle0=-M_PI/2;
10662 double angleNext=0.;
10663 while(nextNode!=startNode)
10667 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10669 if(*node!=tmpOut.back() && *node!=prevNode)
10671 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10672 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10677 res=angle0-angleM+2.*M_PI;
10686 if(nextNode!=startNode)
10688 angle0=angleNext-M_PI;
10691 prevNode=tmpOut.back();
10692 tmpOut.push_back(nextNode);
10695 std::vector<int> tmp3(2*(sz-1));
10696 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10697 std::copy(nodalConnBg+1,nodalConnEnd,it);
10698 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10700 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10703 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10705 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10710 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10711 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10723 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10724 * 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.
10726 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10727 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10728 * \param [in,out] arr array in which the remove operation will be done.
10729 * \param [in,out] arrIndx array in the remove operation will modify
10730 * \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])
10731 * \return true if \b arr and \b arrIndx have been modified, false if not.
10733 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10735 if(!arrIndx || !arr)
10736 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10737 if(offsetForRemoval<0)
10738 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10739 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10740 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10741 int *arrIPtr=arrIndx->getPointer();
10743 int previousArrI=0;
10744 const int *arrPtr=arr->getConstPointer();
10745 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10746 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10748 if(*arrIPtr-previousArrI>offsetForRemoval)
10750 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10752 if(s.find(*work)==s.end())
10753 arrOut.push_back(*work);
10756 previousArrI=*arrIPtr;
10757 *arrIPtr=(int)arrOut.size();
10759 if(arr->getNumberOfTuples()==(int)arrOut.size())
10761 arr->alloc((int)arrOut.size(),1);
10762 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10767 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10768 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10769 * The selection of extraction is done standardly in new2old format.
10770 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10772 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10773 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10774 * \param [in] arrIn arr origin array from which the extraction will be done.
10775 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10776 * \param [out] arrOut the resulting array
10777 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10778 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10780 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10781 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10783 if(!arrIn || !arrIndxIn)
10784 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10785 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10786 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10787 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10788 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10789 const int *arrInPtr=arrIn->getConstPointer();
10790 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10791 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10793 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10794 int maxSizeOfArr=arrIn->getNumberOfTuples();
10795 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10797 arrIo->alloc((int)(sz+1),1);
10798 const int *idsIt=idsOfSelectBg;
10799 int *work=arrIo->getPointer();
10802 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10804 if(*idsIt>=0 && *idsIt<nbOfGrps)
10805 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10808 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10809 throw INTERP_KERNEL::Exception(oss.str().c_str());
10815 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10816 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10817 throw INTERP_KERNEL::Exception(oss.str().c_str());
10820 arro->alloc(lgth,1);
10821 work=arro->getPointer();
10822 idsIt=idsOfSelectBg;
10823 for(std::size_t i=0;i<sz;i++,idsIt++)
10825 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10826 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10829 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10830 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10831 throw INTERP_KERNEL::Exception(oss.str().c_str());
10834 arrOut=arro.retn();
10835 arrIndexOut=arrIo.retn();
10839 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10840 * 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 ).
10841 * The selection of extraction is done standardly in new2old format.
10842 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10844 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10845 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10846 * \param [in] arrIn arr origin array from which the extraction will be done.
10847 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10848 * \param [out] arrOut the resulting array
10849 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10850 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10852 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10853 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10855 if(!arrIn || !arrIndxIn)
10856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10857 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10858 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10860 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10861 const int *arrInPtr=arrIn->getConstPointer();
10862 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10863 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10865 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10866 int maxSizeOfArr=arrIn->getNumberOfTuples();
10867 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10869 arrIo->alloc((int)(sz+1),1);
10870 int idsIt=idsOfSelectStart;
10871 int *work=arrIo->getPointer();
10874 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10876 if(idsIt>=0 && idsIt<nbOfGrps)
10877 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10880 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10881 throw INTERP_KERNEL::Exception(oss.str().c_str());
10887 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10888 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10889 throw INTERP_KERNEL::Exception(oss.str().c_str());
10892 arro->alloc(lgth,1);
10893 work=arro->getPointer();
10894 idsIt=idsOfSelectStart;
10895 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10897 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10898 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10901 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10902 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10903 throw INTERP_KERNEL::Exception(oss.str().c_str());
10906 arrOut=arro.retn();
10907 arrIndexOut=arrIo.retn();
10911 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10912 * 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
10913 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10914 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10916 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10917 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10918 * \param [in] arrIn arr origin array from which the extraction will be done.
10919 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10920 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10921 * \param [in] srcArrIndex index array of \b srcArr
10922 * \param [out] arrOut the resulting array
10923 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10925 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10927 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10928 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10929 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10931 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10935 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10936 std::vector<bool> v(nbOfTuples,true);
10938 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10939 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10940 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10942 if(*it>=0 && *it<nbOfTuples)
10945 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10949 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10950 throw INTERP_KERNEL::Exception(oss.str().c_str());
10953 srcArrIndexPtr=srcArrIndex->getConstPointer();
10954 arrIo->alloc(nbOfTuples+1,1);
10955 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10956 const int *arrInPtr=arrIn->getConstPointer();
10957 const int *srcArrPtr=srcArr->getConstPointer();
10958 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10959 int *arroPtr=arro->getPointer();
10960 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10964 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10965 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10969 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10970 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10971 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10974 arrOut=arro.retn();
10975 arrIndexOut=arrIo.retn();
10979 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10980 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10982 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10983 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10984 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10985 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10986 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10987 * \param [in] srcArrIndex index array of \b srcArr
10989 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10991 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10992 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10994 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10995 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10996 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10997 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10998 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10999 int *arrInOutPtr=arrInOut->getPointer();
11000 const int *srcArrPtr=srcArr->getConstPointer();
11001 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11003 if(*it>=0 && *it<nbOfTuples)
11005 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11006 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11009 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] !";
11010 throw INTERP_KERNEL::Exception(oss.str().c_str());
11015 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11016 throw INTERP_KERNEL::Exception(oss.str().c_str());
11022 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11023 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11024 * 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]].
11025 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11026 * A negative value in \b arrIn means that it is ignored.
11027 * 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.
11029 * \param [in] arrIn arr origin array from which the extraction will be done.
11030 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11031 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11032 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11034 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11036 int seed=0,nbOfDepthPeelingPerformed=0;
11037 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11041 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11042 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11043 * 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]].
11044 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11045 * A negative value in \b arrIn means that it is ignored.
11046 * 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.
11047 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11048 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11049 * \param [in] arrIn arr origin array from which the extraction will be done.
11050 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11051 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11052 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11053 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11054 * \sa MEDCouplingUMesh::partitionBySpreadZone
11056 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11058 nbOfDepthPeelingPerformed=0;
11060 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11061 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11064 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11068 std::vector<bool> fetched(nbOfTuples,false);
11069 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11072 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11074 nbOfDepthPeelingPerformed=0;
11075 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11076 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11077 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11078 std::vector<bool> fetched2(nbOfTuples,false);
11080 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11082 if(*seedElt>=0 && *seedElt<nbOfTuples)
11083 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11085 { 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()); }
11087 const int *arrInPtr=arrIn->getConstPointer();
11088 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11089 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11090 std::vector<int> idsToFetch1(seedBg,seedEnd);
11091 std::vector<int> idsToFetch2;
11092 std::vector<int> *idsToFetch=&idsToFetch1;
11093 std::vector<int> *idsToFetchOther=&idsToFetch2;
11094 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11096 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11097 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11099 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11100 std::swap(idsToFetch,idsToFetchOther);
11101 idsToFetchOther->clear();
11102 nbOfDepthPeelingPerformed++;
11104 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11107 int *retPtr=ret->getPointer();
11108 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11115 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11116 * 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
11117 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11118 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11120 * \param [in] start begin of set of ids of the input extraction (included)
11121 * \param [in] end end of set of ids of the input extraction (excluded)
11122 * \param [in] step step of the set of ids in range mode.
11123 * \param [in] arrIn arr origin array from which the extraction will be done.
11124 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11125 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11126 * \param [in] srcArrIndex index array of \b srcArr
11127 * \param [out] arrOut the resulting array
11128 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11130 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11132 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11133 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11134 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11136 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11137 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11139 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11140 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11142 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11143 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11144 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11146 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11148 if(it>=0 && it<nbOfTuples)
11149 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11152 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11153 throw INTERP_KERNEL::Exception(oss.str().c_str());
11156 srcArrIndexPtr=srcArrIndex->getConstPointer();
11157 arrIo->alloc(nbOfTuples+1,1);
11158 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11159 const int *arrInPtr=arrIn->getConstPointer();
11160 const int *srcArrPtr=srcArr->getConstPointer();
11161 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11162 int *arroPtr=arro->getPointer();
11163 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11165 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11168 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11169 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11173 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11174 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11177 arrOut=arro.retn();
11178 arrIndexOut=arrIo.retn();
11182 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11183 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11185 * \param [in] start begin of set of ids of the input extraction (included)
11186 * \param [in] end end of set of ids of the input extraction (excluded)
11187 * \param [in] step step of the set of ids in range mode.
11188 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11189 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11190 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11191 * \param [in] srcArrIndex index array of \b srcArr
11193 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11195 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11196 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11198 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11199 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11200 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11201 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11202 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11203 int *arrInOutPtr=arrInOut->getPointer();
11204 const int *srcArrPtr=srcArr->getConstPointer();
11205 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11207 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11209 if(it>=0 && it<nbOfTuples)
11211 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11212 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11215 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11216 throw INTERP_KERNEL::Exception(oss.str().c_str());
11221 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11222 throw INTERP_KERNEL::Exception(oss.str().c_str());
11228 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11229 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11230 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11231 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11232 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11234 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11236 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11238 checkFullyDefined();
11239 int mdim=getMeshDimension();
11240 int spaceDim=getSpaceDimension();
11242 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11243 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11244 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11245 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11246 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11247 ret->setCoords(getCoords());
11248 ret->allocateCells((int)partition.size());
11250 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11252 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11257 cell=tmp->buildUnionOf2DMesh();
11260 cell=tmp->buildUnionOf3DMesh();
11263 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11266 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11269 ret->finishInsertingCells();
11274 * This method partitions \b this into contiguous zone.
11275 * This method only needs a well defined connectivity. Coordinates are not considered here.
11276 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11278 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11280 int nbOfCellsCur=getNumberOfCells();
11281 std::vector<DataArrayInt *> ret;
11282 if(nbOfCellsCur<=0)
11284 DataArrayInt *neigh=0,*neighI=0;
11285 computeNeighborsOfCells(neigh,neighI);
11286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11287 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11288 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11290 while(seed<nbOfCellsCur)
11292 int nbOfPeelPerformed=0;
11293 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11294 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11296 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11297 ret.push_back((*it).retn());
11302 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11303 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11305 * \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.
11306 * \return a newly allocated DataArrayInt to be managed by the caller.
11307 * \throw In case of \a code has not the right format (typically of size 3*n)
11309 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11312 std::size_t nb=code.size()/3;
11313 if(code.size()%3!=0)
11314 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11315 ret->alloc((int)nb,2);
11316 int *retPtr=ret->getPointer();
11317 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11319 retPtr[0]=code[3*i+2];
11320 retPtr[1]=code[3*i+2]+code[3*i+1];
11326 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11327 * All cells in \a this are expected to be linear 3D cells.
11328 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11329 * It leads to an increase to number of cells.
11330 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11331 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11332 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11334 * \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.
11335 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11336 * \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.
11337 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11338 * an id of old cell producing it. The caller is to delete this array using
11339 * decrRef() as it is no more needed.
11340 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11342 * \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
11343 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11345 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11346 * \throw If \a this is not fully constituted with linear 3D cells.
11347 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11349 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11351 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11352 checkConnectivityFullyDefined();
11353 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11355 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11356 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11358 int *retPt(ret->getPointer());
11359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11360 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11361 const int *oldc(_nodal_connec->begin());
11362 const int *oldci(_nodal_connec_index->begin());
11363 const double *coords(_coords->begin());
11364 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11366 std::vector<int> a; std::vector<double> b;
11367 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11368 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11369 const int *aa(&a[0]);
11372 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11374 *it=(-(*(it))-1+nbNodes);
11375 addPts->insertAtTheEnd(b.begin(),b.end());
11376 nbNodes+=(int)b.size()/3;
11378 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11379 newConn->insertAtTheEnd(aa,aa+4);
11381 if(!addPts->empty())
11383 addPts->rearrange(3);
11384 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11385 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11386 ret0->setCoords(addPts);
11390 nbOfAdditionalPoints=0;
11391 ret0->setCoords(getCoords());
11393 ret0->setNodalConnectivity(newConn);
11395 ret->computeOffsets2();
11396 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11397 return ret0.retn();
11401 * 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).
11403 * \sa MEDCouplingUMesh::split2DCells
11405 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11407 checkConnectivityFullyDefined();
11408 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11409 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11410 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11411 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11412 int prevPosOfCi(ciPtr[0]);
11413 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11415 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11416 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11417 for(int j=0;j<sz;j++)
11419 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11420 for(int k=0;k<sz2;k++)
11421 *cPtr++=subPtr[offset2+k];
11423 *cPtr++=oldConn[prevPosOfCi+j+2];
11426 prevPosOfCi=ciPtr[1];
11427 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11430 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11431 _nodal_connec->decrRef();
11432 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11435 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11441 int ret(nodesCnter++);
11443 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11444 addCoo.insertAtTheEnd(newPt,newPt+2);
11449 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11455 int ret(nodesCnter++);
11457 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11458 addCoo.insertAtTheEnd(newPt,newPt+2);
11466 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)
11469 int trueStart(start>=0?start:nbOfEdges+start);
11470 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11471 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11476 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11477 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11478 middles.push_back(tmp3+offset);
11481 middles.push_back(connBg[trueStart+nbOfEdges]);
11485 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)
11487 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11488 newConnOfCell->pushBackSilent(tmpEnd);
11493 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11494 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11495 middles.push_back(tmp3+offset);
11498 middles.push_back(connBg[start+nbOfEdges]);
11502 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)
11504 // only the quadratic point to deal with:
11509 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11510 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11511 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11512 middles.push_back(tmp3+offset);
11515 middles.push_back(connBg[start+nbOfEdges]);
11522 * 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 ) .
11523 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11525 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11527 std::size_t sz(std::distance(connBg,connEnd));
11528 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11529 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11531 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11532 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11533 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11534 unsigned nbOfHit(0); // number of fusions operated
11535 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11536 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
11537 INTERP_KERNEL::NormalizedCellType typeOfSon;
11538 std::vector<int> middles;
11540 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11542 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11543 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11544 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11545 posEndElt = posBaseElt+1;
11547 // Look backward first: are the final edges of the cells colinear with the first ones?
11548 // This initializes posBaseElt.
11551 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11553 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11554 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11555 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11556 bool isColinear=eint->areColinears();
11569 // Now move forward:
11570 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11571 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11573 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11574 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11575 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11576 bool isColinear(eint->areColinears());
11588 //push [posBaseElt,posEndElt) in newConnOfCell using e
11589 // 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!
11591 // at the begining of the connectivity (insert type)
11592 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11593 else if((nbOfHit+nbOfTurn) != (nbs-1))
11595 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11596 if ((nbOfHit+nbOfTurn) == (nbs-1))
11597 // at the end (only quad points to deal with)
11598 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11599 posBaseElt=posEndElt;
11602 if(!middles.empty())
11603 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11608 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11610 * \return int - the number of new nodes created.
11611 * \sa MEDCouplingUMesh::split2DCells
11613 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11616 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11618 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11619 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11620 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11621 const double *oldCoordsPtr(getCoords()->begin());
11622 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11623 int prevPosOfCi(ciPtr[0]);
11624 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11626 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11627 for(int j=0;j<sz;j++)
11628 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11629 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11630 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11632 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11636 cPtr[1]=oldConn[prevPosOfCi+2+j];
11637 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11640 std::vector<INTERP_KERNEL::Node *> ns(3);
11641 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11642 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11643 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11644 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11645 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11647 cPtr[1]=subPtr[offset2+k];
11648 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11650 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11652 { cPtr[1]=tmpEnd; }
11653 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11655 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11656 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11659 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11660 _nodal_connec->decrRef();
11661 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11662 addCoo->rearrange(2);
11663 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11665 return addCoo->getNumberOfTuples();
11668 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11670 if(nodalConnec && nodalConnecIndex)
11673 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11674 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11676 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11677 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11681 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11682 _own_cell(true),_cell_id(-1),_nb_cell(0)
11687 _nb_cell=mesh->getNumberOfCells();
11691 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11699 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11700 _own_cell(false),_cell_id(bg-1),
11707 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11710 if(_cell_id<_nb_cell)
11719 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11725 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11727 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11730 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11736 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11744 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11750 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11755 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11760 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11762 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11765 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11770 _nb_cell=mesh->getNumberOfCells();
11774 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11781 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11783 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11784 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11785 if(_cell_id<_nb_cell)
11787 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11788 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11789 int startId=_cell_id;
11790 _cell_id+=nbOfElems;
11791 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11797 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11801 _conn=mesh->getNodalConnectivity()->getPointer();
11802 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11806 void MEDCouplingUMeshCell::next()
11808 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11813 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11816 std::string MEDCouplingUMeshCell::repr() const
11818 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11820 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11822 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11826 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11829 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11831 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11832 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11834 return INTERP_KERNEL::NORM_ERROR;
11837 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11840 if(_conn_lgth!=NOTICABLE_FIRST_VAL)