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;
57 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
62 return new MEDCouplingUMesh;
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
67 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68 ret->setName(meshName);
69 ret->setMeshDimension(meshDim);
74 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
75 * between \a this and the new mesh.
76 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
77 * delete this mesh using decrRef() as it is no more needed.
79 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
85 * Returns a new MEDCouplingMesh which is a copy of \a this one.
86 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
87 * this mesh are shared by the new mesh.
88 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
89 * delete this mesh using decrRef() as it is no more needed.
91 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
93 return new MEDCouplingUMesh(*this,recDeepCpy);
97 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
98 * The coordinates are shared between \a this and the returned instance.
100 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
101 * \sa MEDCouplingUMesh::deepCpy
103 MEDCouplingUMesh *MEDCouplingUMesh::deepCpyConnectivityOnly() const
105 checkConnectivityFullyDefined();
106 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
107 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
108 ret->setConnectivity(c,ci);
112 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
116 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
118 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
119 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
120 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
123 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
125 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
129 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
131 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
132 ret.push_back(_nodal_connec);
133 ret.push_back(_nodal_connec_index);
137 void MEDCouplingUMesh::updateTime() const
139 MEDCouplingPointSet::updateTime();
142 updateTimeWith(*_nodal_connec);
144 if(_nodal_connec_index)
146 updateTimeWith(*_nodal_connec_index);
150 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
155 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
156 * then \a this mesh is most probably is writable, exchangeable and available for most
157 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
158 * this method to check that all is in order with \a this mesh.
159 * \throw If the mesh dimension is not set.
160 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
161 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
162 * \throw If the connectivity data array has more than one component.
163 * \throw If the connectivity data array has a named component.
164 * \throw If the connectivity index data array has more than one component.
165 * \throw If the connectivity index data array has a named component.
167 void MEDCouplingUMesh::checkCoherency() const
170 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
172 MEDCouplingPointSet::checkCoherency();
173 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
175 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
177 std::ostringstream message;
178 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
179 throw INTERP_KERNEL::Exception(message.str().c_str());
184 if(_nodal_connec->getNumberOfComponents()!=1)
185 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
186 if(_nodal_connec->getInfoOnComponent(0)!="")
187 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
191 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
192 if(_nodal_connec_index)
194 if(_nodal_connec_index->getNumberOfComponents()!=1)
195 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
196 if(_nodal_connec_index->getInfoOnComponent(0)!="")
197 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
201 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
205 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
206 * then \a this mesh is most probably is writable, exchangeable and available for all
207 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
208 * method thoroughly checks the nodal connectivity.
209 * \param [in] eps - a not used parameter.
210 * \throw If the mesh dimension is not set.
211 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
212 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
213 * \throw If the connectivity data array has more than one component.
214 * \throw If the connectivity data array has a named component.
215 * \throw If the connectivity index data array has more than one component.
216 * \throw If the connectivity index data array has a named component.
217 * \throw If number of nodes defining an element does not correspond to the type of element.
218 * \throw If the nodal connectivity includes an invalid node id.
220 void MEDCouplingUMesh::checkCoherency1(double eps) const
225 int meshDim=getMeshDimension();
226 int nbOfNodes=getNumberOfNodes();
227 int nbOfCells=getNumberOfCells();
228 const int *ptr=_nodal_connec->getConstPointer();
229 const int *ptrI=_nodal_connec_index->getConstPointer();
230 for(int i=0;i<nbOfCells;i++)
232 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
233 if((int)cm.getDimension()!=meshDim)
235 std::ostringstream oss;
236 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
237 throw INTERP_KERNEL::Exception(oss.str().c_str());
239 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
241 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
243 std::ostringstream oss;
244 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
245 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
246 throw INTERP_KERNEL::Exception(oss.str().c_str());
248 if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
249 if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
251 std::ostringstream oss;
252 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " << nbOfNodesInCell;
253 oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
254 throw INTERP_KERNEL::Exception(oss.str().c_str());
256 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
261 if(nodeId>=nbOfNodes)
263 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
264 throw INTERP_KERNEL::Exception(oss.str().c_str());
269 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
270 throw INTERP_KERNEL::Exception(oss.str().c_str());
274 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
276 std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
277 throw INTERP_KERNEL::Exception(oss.str().c_str());
286 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
287 * then \a this mesh is most probably is writable, exchangeable and available for all
288 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
289 * \param [in] eps - a not used parameter.
290 * \throw If the mesh dimension is not set.
291 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
292 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
293 * \throw If the connectivity data array has more than one component.
294 * \throw If the connectivity data array has a named component.
295 * \throw If the connectivity index data array has more than one component.
296 * \throw If the connectivity index data array has a named component.
297 * \throw If number of nodes defining an element does not correspond to the type of element.
298 * \throw If the nodal connectivity includes an invalid node id.
300 void MEDCouplingUMesh::checkCoherency2(double eps) const
302 checkCoherency1(eps);
306 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
307 * elements contained in the mesh. For more info on the mesh dimension see
308 * \ref MEDCouplingUMeshPage.
309 * \param [in] meshDim - a new mesh dimension.
310 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
312 void MEDCouplingUMesh::setMeshDimension(int meshDim)
314 if(meshDim<-1 || meshDim>3)
315 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
321 * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
322 * 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.
323 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
325 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
327 * \if ENABLE_EXAMPLES
328 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
329 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
332 void MEDCouplingUMesh::allocateCells(int nbOfCells)
335 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
336 if(_nodal_connec_index)
338 _nodal_connec_index->decrRef();
342 _nodal_connec->decrRef();
344 _nodal_connec_index=DataArrayInt::New();
345 _nodal_connec_index->reserve(nbOfCells+1);
346 _nodal_connec_index->pushBackSilent(0);
347 _nodal_connec=DataArrayInt::New();
348 _nodal_connec->reserve(2*nbOfCells);
354 * Appends a cell to the connectivity array. For deeper understanding what is
355 * happening see \ref MEDCouplingUMeshNodalConnectivity.
356 * \param [in] type - type of cell to add.
357 * \param [in] size - number of nodes constituting this cell.
358 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
360 * \if ENABLE_EXAMPLES
361 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
362 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
365 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
367 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
368 if(_nodal_connec_index==0)
369 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
370 if((int)cm.getDimension()==_mesh_dim)
373 if(size!=(int)cm.getNumberOfNodes())
375 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
376 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
377 throw INTERP_KERNEL::Exception(oss.str().c_str());
379 int idx=_nodal_connec_index->back();
381 _nodal_connec_index->pushBackSilent(val);
382 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
387 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
388 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
389 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
390 throw INTERP_KERNEL::Exception(oss.str().c_str());
395 * Compacts data arrays to release unused memory. This method is to be called after
396 * finishing cell insertion using \a this->insertNextCell().
398 * \if ENABLE_EXAMPLES
399 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
400 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
403 void MEDCouplingUMesh::finishInsertingCells()
405 _nodal_connec->pack();
406 _nodal_connec_index->pack();
407 _nodal_connec->declareAsNew();
408 _nodal_connec_index->declareAsNew();
413 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
414 * Useful for python users.
416 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
418 return new MEDCouplingUMeshCellIterator(this);
422 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
423 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
424 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
425 * Useful for python users.
427 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
429 if(!checkConsecutiveCellTypes())
430 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
431 return new MEDCouplingUMeshCellByTypeEntry(this);
435 * Returns a set of all cell types available in \a this mesh.
436 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
437 * \warning this method does not throw any exception even if \a this is not defined.
438 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
440 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
446 * This method returns the sorted list of geometric types in \a this.
447 * 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
448 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
450 * \throw if connectivity in \a this is not correctly defined.
452 * \sa MEDCouplingMesh::getAllGeoTypes
454 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
456 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
457 checkConnectivityFullyDefined();
458 int nbOfCells(getNumberOfCells());
461 if(getMeshLength()<1)
462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
463 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
464 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
465 for(int i=1;i<nbOfCells;i++,ci++)
466 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
467 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
472 * This method is a method that compares \a this and \a other.
473 * This method compares \b all attributes, even names and component names.
475 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
478 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
479 std::ostringstream oss; oss.precision(15);
480 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
483 reason="mesh given in input is not castable in MEDCouplingUMesh !";
486 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
488 if(_mesh_dim!=otherC->_mesh_dim)
490 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
494 if(_types!=otherC->_types)
496 oss << "umesh geometric type mismatch :\nThis geometric types are :";
497 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
498 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
499 oss << "\nOther geometric types are :";
500 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
501 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
505 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
506 if(_nodal_connec==0 || otherC->_nodal_connec==0)
508 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
511 if(_nodal_connec!=otherC->_nodal_connec)
512 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
514 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
517 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
518 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
520 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
523 if(_nodal_connec_index!=otherC->_nodal_connec_index)
524 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
526 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
533 * Checks if data arrays of this mesh (node coordinates, nodal
534 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
536 * \param [in] other - the mesh to compare with.
537 * \param [in] prec - precision value used to compare node coordinates.
538 * \return bool - \a true if the two meshes are same.
540 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
542 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
545 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
547 if(_mesh_dim!=otherC->_mesh_dim)
549 if(_types!=otherC->_types)
551 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
552 if(_nodal_connec==0 || otherC->_nodal_connec==0)
554 if(_nodal_connec!=otherC->_nodal_connec)
555 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
557 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
558 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
560 if(_nodal_connec_index!=otherC->_nodal_connec_index)
561 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
567 * Checks if \a this and \a other meshes are geometrically equivalent with high
568 * probability, else an exception is thrown. The meshes are considered equivalent if
569 * (1) meshes contain the same number of nodes and the same number of elements of the
570 * same types (2) three cells of the two meshes (first, last and middle) are based
571 * on coincident nodes (with a specified precision).
572 * \param [in] other - the mesh to compare with.
573 * \param [in] prec - the precision used to compare nodes of the two meshes.
574 * \throw If the two meshes do not match.
576 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
578 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
579 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
581 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
585 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
586 * cells each node belongs to.
587 * \warning For speed reasons, this method does not check if node ids in the nodal
588 * connectivity correspond to the size of node coordinates array.
589 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
590 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
591 * dividing cell ids in \a revNodal into groups each referring to one
592 * node. Its every element (except the last one) is an index pointing to the
593 * first id of a group of cells. For example cells sharing the node #1 are
594 * described by following range of indices:
595 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
596 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
597 * Number of cells sharing the *i*-th node is
598 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
599 * \throw If the coordinates array is not set.
600 * \throw If the nodal connectivity of cells is not defined.
602 * \if ENABLE_EXAMPLES
603 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
604 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
607 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
610 int nbOfNodes=getNumberOfNodes();
611 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
612 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
613 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
614 const int *conn=_nodal_connec->getConstPointer();
615 const int *connIndex=_nodal_connec_index->getConstPointer();
616 int nbOfCells=getNumberOfCells();
617 int nbOfEltsInRevNodal=0;
618 for(int eltId=0;eltId<nbOfCells;eltId++)
620 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
621 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
622 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
623 if(*iter>=0)//for polyhedrons
625 nbOfEltsInRevNodal++;
626 revNodalIndxPtr[(*iter)+1]++;
629 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
630 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
631 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
632 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
633 for(int eltId=0;eltId<nbOfCells;eltId++)
635 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
636 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
637 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
638 if(*iter>=0)//for polyhedrons
639 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
645 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
650 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
656 if(cm.getOrientationStatus(nb,conn1,conn2))
663 class MinusOneSonsGenerator
666 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
667 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
668 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
669 static const int DELTA=1;
671 const INTERP_KERNEL::CellModel& _cm;
674 class MinusOneSonsGeneratorBiQuadratic
677 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
678 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
679 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
680 static const int DELTA=1;
682 const INTERP_KERNEL::CellModel& _cm;
685 class MinusTwoSonsGenerator
688 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
689 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
690 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
691 static const int DELTA=2;
693 const INTERP_KERNEL::CellModel& _cm;
699 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
700 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
701 * describing correspondence between cells of \a this and the result meshes are
702 * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
703 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
704 * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
705 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
706 * \warning For speed reasons, this method does not check if node ids in the nodal
707 * connectivity correspond to the size of node coordinates array.
708 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
709 * to write this mesh to the MED file, its cells must be sorted using
710 * sortCellsInMEDFileFrmt().
711 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
712 * each cell of \a this mesh.
713 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
714 * dividing cell ids in \a desc into groups each referring to one
715 * cell of \a this mesh. Its every element (except the last one) is an index
716 * pointing to the first id of a group of cells. For example cells of the
717 * result mesh bounding the cell #1 of \a this mesh are described by following
719 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
720 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
721 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
722 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
723 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
724 * by each cell of the result mesh.
725 * \param [in,out] revDescIndx - the array, of length one more than number of cells
726 * in the result mesh,
727 * dividing cell ids in \a revDesc into groups each referring to one
728 * cell of the result mesh the same way as \a descIndx divides \a desc.
729 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
730 * delete this mesh using decrRef() as it is no more needed.
731 * \throw If the coordinates array is not set.
732 * \throw If the nodal connectivity of cells is node defined.
733 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
734 * revDescIndx == NULL.
736 * \if ENABLE_EXAMPLES
737 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
738 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
740 * \sa buildDescendingConnectivity2()
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
744 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
748 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
749 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
750 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
751 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
752 * \sa MEDCouplingUMesh::buildDescendingConnectivity
754 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
757 if(getMeshDimension()!=3)
758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
759 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
763 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
764 * this->getMeshDimension(), that bound cells of \a this mesh. In
765 * addition arrays describing correspondence between cells of \a this and the result
766 * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
767 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
768 * mesh. This method differs from buildDescendingConnectivity() in that apart
769 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
770 * result meshes. So a positive id means that order of nodes in corresponding cells
771 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
772 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
773 * i.e. cell ids are one-based.
774 * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
775 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
776 * \warning For speed reasons, this method does not check if node ids in the nodal
777 * connectivity correspond to the size of node coordinates array.
778 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
779 * to write this mesh to the MED file, its cells must be sorted using
780 * sortCellsInMEDFileFrmt().
781 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
782 * each cell of \a this mesh.
783 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
784 * dividing cell ids in \a desc into groups each referring to one
785 * cell of \a this mesh. Its every element (except the last one) is an index
786 * pointing to the first id of a group of cells. For example cells of the
787 * result mesh bounding the cell #1 of \a this mesh are described by following
789 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
790 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
791 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
792 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
793 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
794 * by each cell of the result mesh.
795 * \param [in,out] revDescIndx - the array, of length one more than number of cells
796 * in the result mesh,
797 * dividing cell ids in \a revDesc into groups each referring to one
798 * cell of the result mesh the same way as \a descIndx divides \a desc.
799 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
800 * shares the node coordinates array with \a this mesh. The caller is to
801 * delete this mesh using decrRef() as it is no more needed.
802 * \throw If the coordinates array is not set.
803 * \throw If the nodal connectivity of cells is node defined.
804 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
805 * revDescIndx == NULL.
807 * \if ENABLE_EXAMPLES
808 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
809 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
811 * \sa buildDescendingConnectivity()
813 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
815 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
819 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
820 * For speed reasons no check of this will be done. This method calls
821 * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
822 * This method lists cell by cell in \b this which are its neighbors. To compute the result
823 * only connectivities are considered.
824 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
825 * The format of return is hence \ref numbering-indirect.
827 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
828 * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
829 * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
830 * is equal to the last values in \b neighborsIndx.
831 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
832 * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
834 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
840 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
842 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
846 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
847 * of MEDCouplingUMesh::computeNeighborsOfCells.
848 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
849 * typically the case to extract a set a neighbours,
850 * excluding a set of meshdim-1 cells in input descending connectivity.
851 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
852 * the result of MEDCouplingUMesh::buildDescendingConnectivity.
853 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
855 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
857 * \param [in] desc descending connectivity array.
858 * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
859 * \param [in] revDesc reverse descending connectivity array.
860 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
861 * \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
862 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
863 * \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.
865 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
866 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
868 if(!desc || !descIndx || !revDesc || !revDescIndx)
869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
870 const int *descPtr=desc->getConstPointer();
871 const int *descIPtr=descIndx->getConstPointer();
872 const int *revDescPtr=revDesc->getConstPointer();
873 const int *revDescIPtr=revDescIndx->getConstPointer();
875 int nbCells=descIndx->getNumberOfTuples()-1;
876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
878 int *out1Ptr=out1->getPointer();
880 out0->reserve(desc->getNumberOfTuples());
881 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
883 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
885 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
887 out0->insertAtTheEnd(s.begin(),s.end());
889 *out1Ptr=out0->getNumberOfTuples();
891 neighbors=out0.retn();
892 neighborsIndx=out1.retn();
896 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
897 * For speed reasons no check of this will be done. This method calls
898 * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
899 * This method lists node by node in \b this which are its neighbors. To compute the result
900 * only connectivities are considered.
901 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
903 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
904 * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
905 * parameter allows to select the right part in this array (\ref numbering-indirect).
906 * The number of tuples is equal to the last values in \b neighborsIndx.
907 * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
908 * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
910 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
913 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
915 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
920 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
925 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
930 mesh1D=const_cast<MEDCouplingUMesh *>(this);
936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
939 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
940 mesh1D->getReverseNodalConnectivity(desc,descIndx);
941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
942 ret0->alloc(desc->getNumberOfTuples(),1);
943 int *r0Pt(ret0->getPointer());
944 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
945 for(int i=0;i<nbNodes;i++,rni++)
947 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
948 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
950 neighbors=ret0.retn();
951 neighborsIdx=descIndx.retn();
957 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
958 * For speed reasons no check of this will be done.
960 template<class SonsGenerator>
961 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
963 if(!desc || !descIndx || !revDesc || !revDescIndx)
964 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
965 checkConnectivityFullyDefined();
966 int nbOfCells=getNumberOfCells();
967 int nbOfNodes=getNumberOfNodes();
968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
969 int *revNodalIndxPtr=revNodalIndx->getPointer();
970 const int *conn=_nodal_connec->getConstPointer();
971 const int *connIndex=_nodal_connec_index->getConstPointer();
972 std::string name="Mesh constituent of "; name+=getName();
973 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
974 ret->setCoords(getCoords());
975 ret->allocateCells(2*nbOfCells);
976 descIndx->alloc(nbOfCells+1,1);
977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
978 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
979 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
981 int pos=connIndex[eltId];
982 int posP1=connIndex[eltId+1];
983 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
984 SonsGenerator sg(cm);
985 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
986 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
987 for(unsigned i=0;i<nbOfSons;i++)
989 INTERP_KERNEL::NormalizedCellType cmsId;
990 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
991 for(unsigned k=0;k<nbOfNodesSon;k++)
993 revNodalIndxPtr[tmp[k]+1]++;
994 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
995 revDesc2->pushBackSilent(eltId);
997 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
999 int nbOfCellsM1=ret->getNumberOfCells();
1000 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1002 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1003 int *revNodalPtr=revNodal->getPointer();
1004 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1005 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1006 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1008 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1009 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1010 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1011 if(*iter>=0)//for polyhedrons
1012 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1015 DataArrayInt *commonCells=0,*commonCellsI=0;
1016 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1018 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1019 int newNbOfCellsM1=-1;
1020 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1021 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1022 std::vector<bool> isImpacted(nbOfCellsM1,false);
1023 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1024 for(int work2=work[0];work2!=work[1];work2++)
1025 isImpacted[commonCellsPtr[work2]]=true;
1026 const int *o2nM1Ptr=o2nM1->getConstPointer();
1027 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1028 const int *n2oM1Ptr=n2oM1->getConstPointer();
1029 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1030 ret2->copyTinyInfoFrom(this);
1031 desc->alloc(descIndx->back(),1);
1032 int *descPtr=desc->getPointer();
1033 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1034 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1037 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1040 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1042 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1043 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1046 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1049 revDesc->reserve(newNbOfCellsM1);
1050 revDescIndx->alloc(newNbOfCellsM1+1,1);
1051 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1052 const int *revDesc2Ptr=revDesc2->getConstPointer();
1053 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1055 int oldCellIdM1=n2oM1Ptr[i];
1056 if(!isImpacted[oldCellIdM1])
1058 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1059 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1063 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1064 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1065 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1073 struct MEDCouplingAccVisit
1075 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1076 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1077 int _new_nb_of_nodes;
1083 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1084 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1085 * array of cell ids. Pay attention that after conversion all algorithms work slower
1086 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1087 * conversion due presence of invalid ids in the array of cells to convert, as a
1088 * result \a this mesh contains some already converted elements. In this case the 2D
1089 * mesh remains valid but 3D mesh becomes \b inconsistent!
1090 * \warning This method can significantly modify the order of geometric types in \a this,
1091 * hence, to write this mesh to the MED file, its cells must be sorted using
1092 * sortCellsInMEDFileFrmt().
1093 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1094 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1095 * cellIdsToConvertBg.
1096 * \throw If the coordinates array is not set.
1097 * \throw If the nodal connectivity of cells is node defined.
1098 * \throw If dimension of \a this mesh is not either 2 or 3.
1100 * \if ENABLE_EXAMPLES
1101 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1102 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1105 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1107 checkFullyDefined();
1108 int dim=getMeshDimension();
1110 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1111 int nbOfCells(getNumberOfCells());
1114 const int *connIndex=_nodal_connec_index->getConstPointer();
1115 int *conn=_nodal_connec->getPointer();
1116 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1118 if(*iter>=0 && *iter<nbOfCells)
1120 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1121 if(!cm.isQuadratic())
1122 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1124 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1128 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1129 oss << " in range [0," << nbOfCells << ") !";
1130 throw INTERP_KERNEL::Exception(oss.str().c_str());
1136 int *connIndex(_nodal_connec_index->getPointer());
1137 const int *connOld(_nodal_connec->getConstPointer());
1138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1139 std::vector<bool> toBeDone(nbOfCells,false);
1140 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1142 if(*iter>=0 && *iter<nbOfCells)
1143 toBeDone[*iter]=true;
1146 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1147 oss << " in range [0," << nbOfCells << ") !";
1148 throw INTERP_KERNEL::Exception(oss.str().c_str());
1151 for(int cellId=0;cellId<nbOfCells;cellId++)
1153 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1154 int lgthOld(posP1-pos-1);
1155 if(toBeDone[cellId])
1157 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1158 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1159 int *tmp(new int[nbOfFaces*lgthOld+1]);
1160 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1161 for(unsigned j=0;j<nbOfFaces;j++)
1163 INTERP_KERNEL::NormalizedCellType type;
1164 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1168 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1169 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1170 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1175 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1176 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1179 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1185 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1186 * polyhedrons (if \a this is a 3D mesh).
1187 * \warning As this method is purely for user-friendliness and no optimization is
1188 * done to avoid construction of a useless vector, this method can be costly
1190 * \throw If the coordinates array is not set.
1191 * \throw If the nodal connectivity of cells is node defined.
1192 * \throw If dimension of \a this mesh is not either 2 or 3.
1194 void MEDCouplingUMesh::convertAllToPoly()
1196 int nbOfCells=getNumberOfCells();
1197 std::vector<int> cellIds(nbOfCells);
1198 for(int i=0;i<nbOfCells;i++)
1200 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1204 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1205 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1206 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1207 * base facet of the volume and the second half of nodes describes an opposite facet
1208 * having the same number of nodes as the base one. This method converts such
1209 * connectivity to a valid polyhedral format where connectivity of each facet is
1210 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1211 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1212 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1213 * a correct orientation of the first facet of a polyhedron, else orientation of a
1214 * corrected cell is reverse.<br>
1215 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1216 * it releases the user from boring description of polyhedra connectivity in the valid
1218 * \throw If \a this->getMeshDimension() != 3.
1219 * \throw If \a this->getSpaceDimension() != 3.
1220 * \throw If the nodal connectivity of cells is not defined.
1221 * \throw If the coordinates array is not set.
1222 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1223 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1225 * \if ENABLE_EXAMPLES
1226 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1227 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1230 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1232 checkFullyDefined();
1233 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1235 int nbOfCells=getNumberOfCells();
1236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1237 newCi->alloc(nbOfCells+1,1);
1238 int *newci=newCi->getPointer();
1239 const int *ci=_nodal_connec_index->getConstPointer();
1240 const int *c=_nodal_connec->getConstPointer();
1242 for(int i=0;i<nbOfCells;i++)
1244 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1245 if(type==INTERP_KERNEL::NORM_POLYHED)
1247 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1249 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1250 throw INTERP_KERNEL::Exception(oss.str().c_str());
1252 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1255 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 !";
1256 throw INTERP_KERNEL::Exception(oss.str().c_str());
1259 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)
1262 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1264 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1265 newC->alloc(newci[nbOfCells],1);
1266 int *newc=newC->getPointer();
1267 for(int i=0;i<nbOfCells;i++)
1269 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1270 if(type==INTERP_KERNEL::NORM_POLYHED)
1272 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1273 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1275 for(std::size_t j=0;j<n1;j++)
1277 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1279 newc[n1+5*j+1]=c[ci[i]+1+j];
1280 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1281 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1282 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1287 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1289 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1290 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1295 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1296 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1297 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1298 * to write this mesh to the MED file, its cells must be sorted using
1299 * sortCellsInMEDFileFrmt().
1300 * \return \c true if at least one cell has been converted, \c false else. In the
1301 * last case the nodal connectivity remains unchanged.
1302 * \throw If the coordinates array is not set.
1303 * \throw If the nodal connectivity of cells is not defined.
1304 * \throw If \a this->getMeshDimension() < 0.
1306 bool MEDCouplingUMesh::unPolyze()
1308 checkFullyDefined();
1309 int mdim=getMeshDimension();
1311 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1314 int nbOfCells=getNumberOfCells();
1317 int initMeshLgth=getMeshLength();
1318 int *conn=_nodal_connec->getPointer();
1319 int *index=_nodal_connec_index->getPointer();
1324 for(int i=0;i<nbOfCells;i++)
1326 lgthOfCurCell=index[i+1]-posOfCurCell;
1327 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1328 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1329 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1333 switch(cm.getDimension())
1337 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1338 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1339 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1344 int nbOfFaces,lgthOfPolyhConn;
1345 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1346 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1351 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1355 ret=ret || (newType!=type);
1356 conn[newPos]=newType;
1358 posOfCurCell=index[i+1];
1363 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1364 newPos+=lgthOfCurCell;
1365 posOfCurCell+=lgthOfCurCell;
1369 if(newPos!=initMeshLgth)
1370 _nodal_connec->reAlloc(newPos);
1377 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1378 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1379 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1381 * \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
1384 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1386 checkFullyDefined();
1387 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1388 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1389 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1390 coords->recenterForMaxPrecision(eps);
1392 int nbOfCells=getNumberOfCells();
1393 const int *conn=_nodal_connec->getConstPointer();
1394 const int *index=_nodal_connec_index->getConstPointer();
1395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1396 connINew->alloc(nbOfCells+1,1);
1397 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1400 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1402 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1404 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1408 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1409 *connINewPtr=connNew->getNumberOfTuples();
1412 setConnectivity(connNew,connINew,false);
1416 * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1417 * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1418 * the format of the returned DataArrayInt instance.
1420 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1421 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1423 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1425 checkConnectivityFullyDefined();
1426 int nbOfCells=getNumberOfCells();
1427 const int *connIndex=_nodal_connec_index->getConstPointer();
1428 const int *conn=_nodal_connec->getConstPointer();
1429 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1430 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1431 std::vector<bool> retS(maxElt,false);
1432 for(int i=0;i<nbOfCells;i++)
1433 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1437 for(int i=0;i<maxElt;i++)
1440 DataArrayInt *ret=DataArrayInt::New();
1442 int *retPtr=ret->getPointer();
1443 for(int i=0;i<maxElt;i++)
1450 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1451 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1453 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1455 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1456 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1457 for(int i=0;i<nbOfCells;i++)
1458 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1461 if(conn[j]<nbOfNodes)
1462 nodeIdsInUse[conn[j]]=true;
1465 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1466 throw INTERP_KERNEL::Exception(oss.str().c_str());
1472 * Finds nodes not used in any cell and returns an array giving a new id to every node
1473 * by excluding the unused nodes, for which the array holds -1. The result array is
1474 * a mapping in "Old to New" mode.
1475 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1476 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1477 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1478 * if the node is unused or a new id else. The caller is to delete this
1479 * array using decrRef() as it is no more needed.
1480 * \throw If the coordinates array is not set.
1481 * \throw If the nodal connectivity of cells is not defined.
1482 * \throw If the nodal connectivity includes an invalid id.
1484 * \if ENABLE_EXAMPLES
1485 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1486 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1488 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1490 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1493 int nbOfNodes(getNumberOfNodes());
1494 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1495 ret->alloc(nbOfNodes,1);
1496 int *traducer=ret->getPointer();
1497 std::fill(traducer,traducer+nbOfNodes,-1);
1498 int nbOfCells=getNumberOfCells();
1499 const int *connIndex=_nodal_connec_index->getConstPointer();
1500 const int *conn=_nodal_connec->getConstPointer();
1501 for(int i=0;i<nbOfCells;i++)
1502 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1505 if(conn[j]<nbOfNodes)
1506 traducer[conn[j]]=1;
1509 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1510 throw INTERP_KERNEL::Exception(oss.str().c_str());
1513 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1514 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1519 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1520 * For each cell in \b this the number of nodes constituting cell is computed.
1521 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1522 * So for pohyhedrons some nodes can be counted several times in the returned result.
1524 * \return a newly allocated array
1525 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1527 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1529 checkConnectivityFullyDefined();
1530 int nbOfCells=getNumberOfCells();
1531 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1532 ret->alloc(nbOfCells,1);
1533 int *retPtr=ret->getPointer();
1534 const int *conn=getNodalConnectivity()->getConstPointer();
1535 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1536 for(int i=0;i<nbOfCells;i++,retPtr++)
1538 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539 *retPtr=connI[i+1]-connI[i]-1;
1541 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1547 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1548 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1550 * \return DataArrayInt * - new object to be deallocated by the caller.
1551 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1553 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1555 checkConnectivityFullyDefined();
1556 int nbOfCells=getNumberOfCells();
1557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1558 ret->alloc(nbOfCells,1);
1559 int *retPtr=ret->getPointer();
1560 const int *conn=getNodalConnectivity()->getConstPointer();
1561 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1562 for(int i=0;i<nbOfCells;i++,retPtr++)
1564 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1565 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1566 *retPtr=(int)s.size();
1570 *retPtr=(int)s.size();
1577 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1578 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1580 * \return a newly allocated array
1582 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1584 checkConnectivityFullyDefined();
1585 int nbOfCells=getNumberOfCells();
1586 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1587 ret->alloc(nbOfCells,1);
1588 int *retPtr=ret->getPointer();
1589 const int *conn=getNodalConnectivity()->getConstPointer();
1590 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1591 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1593 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1594 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1600 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1601 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1602 * array mean that the corresponding old node is no more used.
1603 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1604 * this->getNumberOfNodes() before call of this method. The caller is to
1605 * delete this array using decrRef() as it is no more needed.
1606 * \throw If the coordinates array is not set.
1607 * \throw If the nodal connectivity of cells is not defined.
1608 * \throw If the nodal connectivity includes an invalid id.
1609 * \sa areAllNodesFetched
1611 * \if ENABLE_EXAMPLES
1612 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1613 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1616 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1618 return MEDCouplingPointSet::zipCoordsTraducer();
1622 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1623 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1625 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1630 return AreCellsEqual0(conn,connI,cell1,cell2);
1632 return AreCellsEqual1(conn,connI,cell1,cell2);
1634 return AreCellsEqual2(conn,connI,cell1,cell2);
1636 return AreCellsEqual3(conn,connI,cell1,cell2);
1638 return AreCellsEqual7(conn,connI,cell1,cell2);
1640 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1644 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1646 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1648 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1649 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1654 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1656 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1658 int sz=connI[cell1+1]-connI[cell1];
1659 if(sz==connI[cell2+1]-connI[cell2])
1661 if(conn[connI[cell1]]==conn[connI[cell2]])
1663 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1664 unsigned dim=cm.getDimension();
1670 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1671 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1672 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1673 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1674 return work!=tmp+sz1?1:0;
1677 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1680 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1687 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1689 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1691 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1693 if(conn[connI[cell1]]==conn[connI[cell2]])
1695 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1696 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1704 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1706 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1708 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1710 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1711 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1718 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1720 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1722 int sz=connI[cell1+1]-connI[cell1];
1723 if(sz==connI[cell2+1]-connI[cell2])
1725 if(conn[connI[cell1]]==conn[connI[cell2]])
1727 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1728 unsigned dim=cm.getDimension();
1734 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1735 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1736 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1737 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1742 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1743 std::reverse_iterator<int *> it2((int *)tmp);
1744 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1750 return work!=tmp+sz1?1:0;
1753 {//case of SEG2 and SEG3
1754 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1756 if(!cm.isQuadratic())
1758 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1759 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1760 if(std::equal(it1,it2,conn+connI[cell2]+1))
1766 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])
1773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1780 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1781 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1782 * and result remains unchanged.
1783 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1784 * If in 'candidates' pool -1 value is considered as an empty value.
1785 * WARNING this method returns only ONE set of result !
1787 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1789 if(candidates.size()<1)
1792 std::vector<int>::const_iterator iter=candidates.begin();
1793 int start=(*iter++);
1794 for(;iter!=candidates.end();iter++)
1796 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1801 result->pushBackSilent(start);
1805 result->pushBackSilent(*iter);
1807 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1814 * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1816 * This method keeps the coordiantes of \a this. This method is time consuming.
1818 * \param [in] compType input specifying the technique used to compare cells each other.
1819 * - 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.
1820 * - 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)
1821 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1822 * - 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
1823 * can be used for users not sensitive to orientation of cell
1824 * \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.
1825 * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1826 * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1827 * \return the correspondance array old to new in a newly allocated array.
1830 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1833 getReverseNodalConnectivity(revNodal,revNodalI);
1834 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1837 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1838 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1841 int nbOfCells=nodalI->getNumberOfTuples()-1;
1842 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1843 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1844 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1845 std::vector<bool> isFetched(nbOfCells,false);
1848 for(int i=0;i<nbOfCells;i++)
1852 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1853 std::vector<int> v,v2;
1854 if(connOfNode!=connPtr+connIPtr[i+1])
1856 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1857 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1860 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1864 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1865 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1866 v2.resize(std::distance(v2.begin(),it));
1870 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1872 int pos=commonCellsI->back();
1873 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1874 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1875 isFetched[*it]=true;
1883 for(int i=startCellId;i<nbOfCells;i++)
1887 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1888 std::vector<int> v,v2;
1889 if(connOfNode!=connPtr+connIPtr[i+1])
1891 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1894 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1898 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1899 v2.resize(std::distance(v2.begin(),it));
1903 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1905 int pos=commonCellsI->back();
1906 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1907 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1908 isFetched[*it]=true;
1914 commonCellsArr=commonCells.retn();
1915 commonCellsIArr=commonCellsI.retn();
1919 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1920 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1921 * than \a other->getNumberOfCells() in the returned array means that there is no
1922 * corresponding cell in \a this mesh.
1923 * It is expected that \a this and \a other meshes share the same node coordinates
1924 * array, if it is not so an exception is thrown.
1925 * \param [in] other - the mesh to compare with.
1926 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1927 * valid values [0,1,2], see zipConnectivityTraducer().
1928 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1929 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1930 * values. The caller is to delete this array using
1931 * decrRef() as it is no more needed.
1932 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1935 * \if ENABLE_EXAMPLES
1936 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1937 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1939 * \sa checkDeepEquivalOnSameNodesWith()
1940 * \sa checkGeoEquivalWith()
1942 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1944 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1945 int nbOfCells=getNumberOfCells();
1946 static const int possibleCompType[]={0,1,2};
1947 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1949 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1950 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1952 throw INTERP_KERNEL::Exception(oss.str().c_str());
1954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1955 arr=o2n->substr(nbOfCells);
1956 arr->setName(other->getName());
1958 if(other->getNumberOfCells()==0)
1960 return arr->getMaxValue(tmp)<nbOfCells;
1964 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1965 * This method tries to determine if \b other is fully included in \b this.
1966 * The main difference is that this method is not expected to throw exception.
1967 * This method has two outputs :
1969 * \param other other mesh
1970 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1971 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1973 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1975 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1976 DataArrayInt *commonCells=0,*commonCellsI=0;
1977 int thisNbCells=getNumberOfCells();
1978 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1980 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1981 int otherNbCells=other->getNumberOfCells();
1982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1983 arr2->alloc(otherNbCells,1);
1984 arr2->fillWithZero();
1985 int *arr2Ptr=arr2->getPointer();
1986 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1987 for(int i=0;i<nbOfCommon;i++)
1989 int start=commonCellsPtr[commonCellsIPtr[i]];
1990 if(start<thisNbCells)
1992 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1994 int sig=commonCellsPtr[j]>0?1:-1;
1995 int val=std::abs(commonCellsPtr[j])-1;
1996 if(val>=thisNbCells)
1997 arr2Ptr[val-thisNbCells]=sig*(start+1);
2001 arr2->setName(other->getName());
2002 if(arr2->presenceOfValue(0))
2008 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2011 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2012 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2014 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2015 std::vector<const MEDCouplingUMesh *> ms(2);
2018 return MergeUMeshesOnSameCoords(ms);
2022 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2023 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2024 * cellIds is not given explicitely but by a range python like.
2029 * \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.
2030 * \return a newly allocated
2032 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2033 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2035 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2037 if(getMeshDimension()!=-1)
2038 return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords));
2041 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2043 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2045 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2047 return const_cast<MEDCouplingUMesh *>(this);
2052 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2053 * The result mesh shares or not the node coordinates array with \a this mesh depending
2054 * on \a keepCoords parameter.
2055 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2056 * to write this mesh to the MED file, its cells must be sorted using
2057 * sortCellsInMEDFileFrmt().
2058 * \param [in] begin - an array of cell ids to include to the new mesh.
2059 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2060 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2061 * array of \a this mesh, else "free" nodes are removed from the result mesh
2062 * by calling zipCoords().
2063 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2064 * to delete this mesh using decrRef() as it is no more needed.
2065 * \throw If the coordinates array is not set.
2066 * \throw If the nodal connectivity of cells is not defined.
2067 * \throw If any cell id in the array \a begin is not valid.
2069 * \if ENABLE_EXAMPLES
2070 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2071 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2074 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2076 if(getMeshDimension()!=-1)
2077 return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2081 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2083 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2085 return const_cast<MEDCouplingUMesh *>(this);
2090 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2092 * 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.
2093 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2094 * The number of cells of \b this will remain the same with this method.
2096 * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2097 * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2098 * \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 ).
2099 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2101 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2103 checkConnectivityFullyDefined();
2104 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2105 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2106 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2107 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2109 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2110 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2111 throw INTERP_KERNEL::Exception(oss.str().c_str());
2113 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2114 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2116 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2117 throw INTERP_KERNEL::Exception(oss.str().c_str());
2119 int nbOfCells=getNumberOfCells();
2120 bool easyAssign=true;
2121 const int *connI=_nodal_connec_index->getConstPointer();
2122 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2123 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2125 if(*it>=0 && *it<nbOfCells)
2127 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2131 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2132 throw INTERP_KERNEL::Exception(oss.str().c_str());
2137 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2142 DataArrayInt *arrOut=0,*arrIOut=0;
2143 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2146 setConnectivity(arrOut,arrIOut,true);
2150 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2152 checkConnectivityFullyDefined();
2153 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2154 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2155 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2156 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2158 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2159 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2160 throw INTERP_KERNEL::Exception(oss.str().c_str());
2162 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2163 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2165 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2166 throw INTERP_KERNEL::Exception(oss.str().c_str());
2168 int nbOfCells=getNumberOfCells();
2169 bool easyAssign=true;
2170 const int *connI=_nodal_connec_index->getConstPointer();
2171 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2173 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2175 if(it>=0 && it<nbOfCells)
2177 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2181 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2182 throw INTERP_KERNEL::Exception(oss.str().c_str());
2187 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2192 DataArrayInt *arrOut=0,*arrIOut=0;
2193 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2195 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2196 setConnectivity(arrOut,arrIOut,true);
2201 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2202 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2203 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2204 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2206 * \param [in] begin input start of array of node ids.
2207 * \param [in] end input end of array of node ids.
2208 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2209 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2211 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2214 checkConnectivityFullyDefined();
2216 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2217 std::vector<bool> fastFinder(sz,false);
2218 for(const int *work=begin;work!=end;work++)
2219 if(*work>=0 && *work<sz)
2220 fastFinder[*work]=true;
2221 int nbOfCells=getNumberOfCells();
2222 const int *conn=getNodalConnectivity()->getConstPointer();
2223 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2224 for(int i=0;i<nbOfCells;i++)
2226 int ref=0,nbOfHit=0;
2227 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2231 if(fastFinder[*work2])
2234 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2235 cellIdsKept->pushBackSilent(i);
2237 cellIdsKeptArr=cellIdsKept.retn();
2241 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242 * this->getMeshDimension(), that bound some cells of \a this mesh.
2243 * The cells of lower dimension to include to the result mesh are selected basing on
2244 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2245 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2246 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2247 * created mesh shares the node coordinates array with \a this mesh.
2248 * \param [in] begin - the array of node ids.
2249 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2250 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2251 * array \a begin are added, else cells whose any node is in the
2252 * array \a begin are added.
2253 * \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2254 * to delete this mesh using decrRef() as it is no more needed.
2255 * \throw If the coordinates array is not set.
2256 * \throw If the nodal connectivity of cells is not defined.
2257 * \throw If any node id in \a begin is not valid.
2259 * \if ENABLE_EXAMPLES
2260 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2261 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2264 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2267 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2268 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2269 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2270 return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2274 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2275 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2276 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2277 * array of \a this mesh, else "free" nodes are removed from the result mesh
2278 * by calling zipCoords().
2279 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2280 * to delete this mesh using decrRef() as it is no more needed.
2281 * \throw If the coordinates array is not set.
2282 * \throw If the nodal connectivity of cells is not defined.
2284 * \if ENABLE_EXAMPLES
2285 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2286 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2289 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2291 DataArrayInt *desc=DataArrayInt::New();
2292 DataArrayInt *descIndx=DataArrayInt::New();
2293 DataArrayInt *revDesc=DataArrayInt::New();
2294 DataArrayInt *revDescIndx=DataArrayInt::New();
2296 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2299 descIndx->decrRef();
2300 int nbOfCells=meshDM1->getNumberOfCells();
2301 const int *revDescIndxC=revDescIndx->getConstPointer();
2302 std::vector<int> boundaryCells;
2303 for(int i=0;i<nbOfCells;i++)
2304 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2305 boundaryCells.push_back(i);
2306 revDescIndx->decrRef();
2307 MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2312 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2313 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2314 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2316 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2318 checkFullyDefined();
2319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2324 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2325 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2329 const int *revDescPtr=revDesc->getConstPointer();
2330 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2331 int nbOfCells=getNumberOfCells();
2332 std::vector<bool> ret1(nbOfCells,false);
2334 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2335 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2336 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2338 DataArrayInt *ret2=DataArrayInt::New();
2340 int *ret2Ptr=ret2->getPointer();
2342 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2345 ret2->setName("BoundaryCells");
2350 * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2351 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2352 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2353 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2355 * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2356 * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2357 * equals a cell in \b otherDimM1OnSameCoords.
2359 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2360 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2362 * \param [in] otherDimM1OnSameCoords
2363 * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2364 * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2365 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2367 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2369 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2370 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2371 checkConnectivityFullyDefined();
2372 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2373 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2374 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2377 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2379 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2380 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2381 DataArrayInt *idsOtherInConsti=0;
2382 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2385 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2387 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2388 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2390 s1arr_renum1->sort();
2391 cellIdsRk0=s0arr.retn();
2392 //cellIdsRk1=s_renum1.retn();
2393 cellIdsRk1=s1arr_renum1.retn();
2397 * 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
2398 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2400 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2402 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2409 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2410 revDesc=0; desc=0; descIndx=0;
2411 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2413 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2417 * Finds nodes lying on the boundary of \a this mesh.
2418 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2419 * nodes. The caller is to delete this array using decrRef() as it is no
2421 * \throw If the coordinates array is not set.
2422 * \throw If the nodal connectivity of cells is node defined.
2424 * \if ENABLE_EXAMPLES
2425 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2426 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2429 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2431 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2432 return skin->computeFetchedNodeIds();
2435 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2438 return const_cast<MEDCouplingUMesh *>(this);
2442 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2443 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2444 * 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.
2445 * 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.
2446 * 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.
2448 * \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
2449 * parameter is altered during the call.
2450 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2451 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2452 * \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.
2454 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2456 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2457 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2459 typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2461 checkFullyDefined();
2462 otherDimM1OnSameCoords.checkFullyDefined();
2463 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2465 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2467 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2468 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2469 DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2470 DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2471 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2472 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2473 DAInt s1=m0Part->computeFetchedNodeIds();
2474 DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2475 DAInt s3=s2->buildSubstraction(s1);
2476 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2478 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2479 int nCells2 = m0Part2->getNumberOfCells();
2480 DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2481 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2482 // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2483 DataArrayInt *tmp00=0,*tmp11=0;
2484 MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2485 DAInt neighInit00(tmp00);
2486 DAInt neighIInit00(tmp11);
2487 // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2488 DataArrayInt *idsTmp=0;
2489 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2492 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2493 // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2494 // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2495 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2496 DataArrayInt *tmp0=0,*tmp1=0;
2497 // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2498 // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2499 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2500 DAInt neigh00(tmp0);
2501 DAInt neighI00(tmp1);
2503 // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2504 int seed = 0, nIter = 0;
2505 int nIterMax = nCells2+1; // Safety net for the loop
2506 DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2507 hitCells->fillWithValue(-1);
2508 DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2509 cellsToModifyConn0_torenum->alloc(0,1);
2510 while (nIter < nIterMax)
2512 DAInt t = hitCells->getIdsEqual(-1);
2513 if (!t->getNumberOfTuples())
2515 // Connex zone without the crack (to compute the next seed really)
2517 DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2519 for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2520 hitCells->setIJ(*ptr,0,1);
2521 // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2522 DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2523 cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2524 // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2525 DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2526 DAInt nonHitCells = hitCells->getIdsEqual(-1);
2527 DAInt intersec = nonHitCells->buildIntersection(comple);
2528 if (intersec->getNumberOfTuples())
2529 { seed = intersec->getIJ(0,0); }
2534 if (nIter >= nIterMax)
2535 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2537 DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2538 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2539 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2541 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2542 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2543 nodeIdsToDuplicate=s3.retn();
2547 * This method operates a modification of the connectivity and coords in \b this.
2548 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2549 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2550 * 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
2551 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2552 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2554 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2556 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2557 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2559 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2561 int nbOfNodes=getNumberOfNodes();
2562 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2563 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2567 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2568 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2570 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2572 * \sa renumberNodesInConn
2574 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2576 checkConnectivityFullyDefined();
2577 int *conn(getNodalConnectivity()->getPointer());
2578 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2579 int nbOfCells(getNumberOfCells());
2580 for(int i=0;i<nbOfCells;i++)
2581 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2583 int& node=conn[iconn];
2584 if(node>=0)//avoid polyhedron separator
2589 _nodal_connec->declareAsNew();
2594 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2595 * 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
2598 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2600 checkConnectivityFullyDefined();
2601 int *conn(getNodalConnectivity()->getPointer());
2602 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2603 int nbOfCells(getNumberOfCells());
2604 for(int i=0;i<nbOfCells;i++)
2605 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2607 int& node=conn[iconn];
2608 if(node>=0)//avoid polyhedron separator
2610 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2611 if(it!=newNodeNumbersO2N.end())
2617 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2618 throw INTERP_KERNEL::Exception(oss.str().c_str());
2622 _nodal_connec->declareAsNew();
2627 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2628 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2629 * This method is a generalization of shiftNodeNumbersInConn().
2630 * \warning This method performs no check of validity of new ids. **Use it with care !**
2631 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2632 * this->getNumberOfNodes(), in "Old to New" mode.
2633 * See \ref numbering for more info on renumbering modes.
2634 * \throw If the nodal connectivity of cells is not defined.
2636 * \if ENABLE_EXAMPLES
2637 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2638 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2641 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2643 checkConnectivityFullyDefined();
2644 int *conn=getNodalConnectivity()->getPointer();
2645 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2646 int nbOfCells(getNumberOfCells());
2647 for(int i=0;i<nbOfCells;i++)
2648 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2650 int& node=conn[iconn];
2651 if(node>=0)//avoid polyhedron separator
2653 node=newNodeNumbersO2N[node];
2656 _nodal_connec->declareAsNew();
2661 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2662 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2663 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2665 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2667 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2669 checkConnectivityFullyDefined();
2670 int *conn=getNodalConnectivity()->getPointer();
2671 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2672 int nbOfCells=getNumberOfCells();
2673 for(int i=0;i<nbOfCells;i++)
2674 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2676 int& node=conn[iconn];
2677 if(node>=0)//avoid polyhedron separator
2682 _nodal_connec->declareAsNew();
2687 * This method operates a modification of the connectivity in \b this.
2688 * 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.
2689 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2690 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2691 * 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
2692 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2693 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2695 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2696 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2698 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2699 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2700 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2702 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2704 checkConnectivityFullyDefined();
2705 std::map<int,int> m;
2707 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2709 int *conn=getNodalConnectivity()->getPointer();
2710 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2711 int nbOfCells=getNumberOfCells();
2712 for(int i=0;i<nbOfCells;i++)
2713 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2715 int& node=conn[iconn];
2716 if(node>=0)//avoid polyhedron separator
2718 std::map<int,int>::iterator it=m.find(node);
2727 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2729 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2730 * After the call of this method the number of cells remains the same as before.
2732 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2733 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2734 * be strictly in [0;this->getNumberOfCells()).
2736 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2737 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2738 * should be contained in[0;this->getNumberOfCells()).
2740 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2743 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2745 checkConnectivityFullyDefined();
2746 int nbCells=getNumberOfCells();
2747 const int *array=old2NewBg;
2749 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2751 const int *conn=_nodal_connec->getConstPointer();
2752 const int *connI=_nodal_connec_index->getConstPointer();
2753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2754 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2755 const int *n2oPtr=n2o->begin();
2756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2757 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2758 newConn->copyStringInfoFrom(*_nodal_connec);
2759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2760 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2761 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2763 int *newC=newConn->getPointer();
2764 int *newCI=newConnI->getPointer();
2767 for(int i=0;i<nbCells;i++)
2770 int nbOfElts=connI[pos+1]-connI[pos];
2771 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2776 setConnectivity(newConn,newConnI);
2778 free(const_cast<int *>(array));
2782 * Finds cells whose bounding boxes intersect a given bounding box.
2783 * \param [in] bbox - an array defining the bounding box via coordinates of its
2784 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2786 * \param [in] eps - a factor used to increase size of the bounding box of cell
2787 * before comparing it with \a bbox. This factor is multiplied by the maximal
2788 * extent of the bounding box of cell to produce an addition to this bounding box.
2789 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2790 * cells. The caller is to delete this array using decrRef() as it is no more
2792 * \throw If the coordinates array is not set.
2793 * \throw If the nodal connectivity of cells is not defined.
2795 * \if ENABLE_EXAMPLES
2796 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2797 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2800 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2802 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2803 if(getMeshDimension()==-1)
2805 elems->pushBackSilent(0);
2806 return elems.retn();
2808 int dim=getSpaceDimension();
2809 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2810 const int* conn = getNodalConnectivity()->getConstPointer();
2811 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2812 const double* coords = getCoords()->getConstPointer();
2813 int nbOfCells=getNumberOfCells();
2814 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2816 for (int i=0; i<dim; i++)
2818 elem_bb[i*2]=std::numeric_limits<double>::max();
2819 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2822 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2824 int node= conn[inode];
2825 if(node>=0)//avoid polyhedron separator
2827 for (int idim=0; idim<dim; idim++)
2829 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2831 elem_bb[idim*2] = coords[node*dim+idim] ;
2833 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2835 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2840 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2841 elems->pushBackSilent(ielem);
2843 return elems.retn();
2847 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2848 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2849 * added in 'elems' parameter.
2851 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2854 if(getMeshDimension()==-1)
2856 elems->pushBackSilent(0);
2857 return elems.retn();
2859 int dim=getSpaceDimension();
2860 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2861 const int* conn = getNodalConnectivity()->getConstPointer();
2862 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2863 const double* coords = getCoords()->getConstPointer();
2864 int nbOfCells=getNumberOfCells();
2865 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2867 for (int i=0; i<dim; i++)
2869 elem_bb[i*2]=std::numeric_limits<double>::max();
2870 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2873 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2875 int node= conn[inode];
2876 if(node>=0)//avoid polyhedron separator
2878 for (int idim=0; idim<dim; idim++)
2880 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2882 elem_bb[idim*2] = coords[node*dim+idim] ;
2884 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2886 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2891 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2892 elems->pushBackSilent(ielem);
2894 return elems.retn();
2898 * Returns a type of a cell by its id.
2899 * \param [in] cellId - the id of the cell of interest.
2900 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2901 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2903 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2905 const int *ptI=_nodal_connec_index->getConstPointer();
2906 const int *pt=_nodal_connec->getConstPointer();
2907 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2908 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2911 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2912 throw INTERP_KERNEL::Exception(oss.str().c_str());
2917 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2918 * This method does not throw exception if geometric type \a type is not in \a this.
2919 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2920 * The coordinates array is not considered here.
2922 * \param [in] type the geometric type
2923 * \return cell ids in this having geometric type \a type.
2925 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2930 checkConnectivityFullyDefined();
2931 int nbCells=getNumberOfCells();
2932 int mdim=getMeshDimension();
2933 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2934 if(mdim!=(int)cm.getDimension())
2935 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2936 const int *ptI=_nodal_connec_index->getConstPointer();
2937 const int *pt=_nodal_connec->getConstPointer();
2938 for(int i=0;i<nbCells;i++)
2940 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2941 ret->pushBackSilent(i);
2947 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2949 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2951 const int *ptI=_nodal_connec_index->getConstPointer();
2952 const int *pt=_nodal_connec->getConstPointer();
2953 int nbOfCells=getNumberOfCells();
2955 for(int i=0;i<nbOfCells;i++)
2956 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2962 * Returns the nodal connectivity of a given cell.
2963 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2964 * all returned node ids can be used in getCoordinatesOfNode().
2965 * \param [in] cellId - an id of the cell of interest.
2966 * \param [in,out] conn - a vector where the node ids are appended. It is not
2967 * cleared before the appending.
2968 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2970 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2972 const int *ptI=_nodal_connec_index->getConstPointer();
2973 const int *pt=_nodal_connec->getConstPointer();
2974 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2979 std::string MEDCouplingUMesh::simpleRepr() const
2981 static const char msg0[]="No coordinates specified !";
2982 std::ostringstream ret;
2983 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2984 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2986 double tt=getTime(tmpp1,tmpp2);
2987 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2988 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2990 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2992 { ret << " Mesh dimension has not been set or is invalid !"; }
2995 const int spaceDim=getSpaceDimension();
2996 ret << spaceDim << "\nInfo attached on space dimension : ";
2997 for(int i=0;i<spaceDim;i++)
2998 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3002 ret << msg0 << "\n";
3003 ret << "Number of nodes : ";
3005 ret << getNumberOfNodes() << "\n";
3007 ret << msg0 << "\n";
3008 ret << "Number of cells : ";
3009 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3010 ret << getNumberOfCells() << "\n";
3012 ret << "No connectivity specified !" << "\n";
3013 ret << "Cell types present : ";
3014 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3016 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3017 ret << cm.getRepr() << " ";
3023 std::string MEDCouplingUMesh::advancedRepr() const
3025 std::ostringstream ret;
3026 ret << simpleRepr();
3027 ret << "\nCoordinates array : \n___________________\n\n";
3029 _coords->reprWithoutNameStream(ret);
3031 ret << "No array set !\n";
3032 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3033 reprConnectivityOfThisLL(ret);
3038 * This method returns a C++ code that is a dump of \a this.
3039 * This method will throw if this is not fully defined.
3041 std::string MEDCouplingUMesh::cppRepr() const
3043 static const char coordsName[]="coords";
3044 static const char connName[]="conn";
3045 static const char connIName[]="connI";
3046 checkFullyDefined();
3047 std::ostringstream ret; ret << "// coordinates" << std::endl;
3048 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3049 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3050 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3051 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3052 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3053 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3054 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3058 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3060 std::ostringstream ret;
3061 reprConnectivityOfThisLL(ret);
3066 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3067 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3068 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3071 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3072 * 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
3073 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3075 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3077 int mdim=getMeshDimension();
3079 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3080 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3082 bool needToCpyCT=true;
3085 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3093 if(!_nodal_connec_index)
3095 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3100 tmp2=_nodal_connec_index;
3103 ret->setConnectivity(tmp1,tmp2,false);
3108 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3109 ret->setCoords(coords);
3112 ret->setCoords(_coords);
3116 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3118 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3120 int nbOfCells=getNumberOfCells();
3121 const int *c=_nodal_connec->getConstPointer();
3122 const int *ci=_nodal_connec_index->getConstPointer();
3123 for(int i=0;i<nbOfCells;i++)
3125 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3126 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3127 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3132 stream << "Connectivity not defined !\n";
3135 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3137 const int *ptI=_nodal_connec_index->getConstPointer();
3138 const int *pt=_nodal_connec->getConstPointer();
3139 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3140 return ptI[cellId+1]-ptI[cellId]-1;
3142 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3146 * Returns types of cells of the specified part of \a this mesh.
3147 * This method avoids computing sub-mesh explicitely to get its types.
3148 * \param [in] begin - an array of cell ids of interest.
3149 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3150 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3151 * describing the cell types.
3152 * \throw If the coordinates array is not set.
3153 * \throw If the nodal connectivity of cells is not defined.
3154 * \sa getAllGeoTypes()
3156 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3158 checkFullyDefined();
3159 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3160 const int *conn=_nodal_connec->getConstPointer();
3161 const int *connIndex=_nodal_connec_index->getConstPointer();
3162 for(const int *w=begin;w!=end;w++)
3163 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3168 * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3169 * Optionally updates
3170 * a set of types of cells constituting \a this mesh.
3171 * This method is for advanced users having prepared their connectivity before. For
3172 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3173 * \param [in] conn - the nodal connectivity array.
3174 * \param [in] connIndex - the nodal connectivity index array.
3175 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3178 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3180 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3181 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3182 if(isComputingTypes)
3188 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3189 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3191 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3192 _nodal_connec(0),_nodal_connec_index(0),
3193 _types(other._types)
3195 if(other._nodal_connec)
3196 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3197 if(other._nodal_connec_index)
3198 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3201 MEDCouplingUMesh::~MEDCouplingUMesh()
3204 _nodal_connec->decrRef();
3205 if(_nodal_connec_index)
3206 _nodal_connec_index->decrRef();
3210 * Recomputes a set of cell types of \a this mesh. For more info see
3211 * \ref MEDCouplingUMeshNodalConnectivity.
3213 void MEDCouplingUMesh::computeTypes()
3215 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3219 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3221 void MEDCouplingUMesh::checkFullyDefined() const
3223 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3224 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3228 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3230 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3232 if(!_nodal_connec_index || !_nodal_connec)
3233 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3237 * Returns a number of cells constituting \a this mesh.
3238 * \return int - the number of cells in \a this mesh.
3239 * \throw If the nodal connectivity of cells is not defined.
3241 int MEDCouplingUMesh::getNumberOfCells() const
3243 if(_nodal_connec_index)
3244 return _nodal_connec_index->getNumberOfTuples()-1;
3249 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3253 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3254 * mesh. For more info see \ref meshes.
3255 * \return int - the dimension of \a this mesh.
3256 * \throw If the mesh dimension is not defined using setMeshDimension().
3258 int MEDCouplingUMesh::getMeshDimension() const
3261 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3266 * Returns a length of the nodal connectivity array.
3267 * This method is for test reason. Normally the integer returned is not useable by
3268 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3269 * \return int - the length of the nodal connectivity array.
3271 int MEDCouplingUMesh::getMeshLength() const
3273 return _nodal_connec->getNbOfElems();
3277 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3279 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3281 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3282 tinyInfo.push_back(getMeshDimension());
3283 tinyInfo.push_back(getNumberOfCells());
3285 tinyInfo.push_back(getMeshLength());
3287 tinyInfo.push_back(-1);
3291 * First step of unserialization process.
3293 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3295 return tinyInfo[6]<=0;
3299 * Second step of serialization process.
3300 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3303 * \param littleStrings
3305 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3307 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3309 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3313 * Third and final step of serialization process.
3315 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3317 MEDCouplingPointSet::serialize(a1,a2);
3318 if(getMeshDimension()>-1)
3320 a1=DataArrayInt::New();
3321 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3322 int *ptA1=a1->getPointer();
3323 const int *conn=getNodalConnectivity()->getConstPointer();
3324 const int *index=getNodalConnectivityIndex()->getConstPointer();
3325 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3326 std::copy(conn,conn+getMeshLength(),ptA1);
3333 * Second and final unserialization process.
3334 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3336 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3338 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3339 setMeshDimension(tinyInfo[5]);
3343 const int *recvBuffer=a1->getConstPointer();
3344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3345 myConnecIndex->alloc(tinyInfo[6]+1,1);
3346 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3348 myConnec->alloc(tinyInfo[7],1);
3349 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3350 setConnectivity(myConnec, myConnecIndex);
3355 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3356 * CellIds are given using range specified by a start an end and step.
3358 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3360 checkFullyDefined();
3361 int ncell=getNumberOfCells();
3362 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3363 ret->_mesh_dim=_mesh_dim;
3364 ret->setCoords(_coords);
3365 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3367 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3369 const int *conn=_nodal_connec->getConstPointer();
3370 const int *connIndex=_nodal_connec_index->getConstPointer();
3371 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3373 if(work>=0 && work<ncell)
3375 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3379 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3380 throw INTERP_KERNEL::Exception(oss.str().c_str());
3383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3384 int *newConnPtr=newConn->getPointer();
3385 std::set<INTERP_KERNEL::NormalizedCellType> types;
3387 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3389 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3390 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3392 ret->setConnectivity(newConn,newConnI,false);
3394 ret->copyTinyInfoFrom(this);
3399 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3400 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3401 * The return newly allocated mesh will share the same coordinates as \a this.
3403 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3405 checkConnectivityFullyDefined();
3406 int ncell=getNumberOfCells();
3407 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3408 ret->_mesh_dim=_mesh_dim;
3409 ret->setCoords(_coords);
3410 std::size_t nbOfElemsRet=std::distance(begin,end);
3411 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3413 const int *conn=_nodal_connec->getConstPointer();
3414 const int *connIndex=_nodal_connec_index->getConstPointer();
3416 for(const int *work=begin;work!=end;work++,newNbring++)
3418 if(*work>=0 && *work<ncell)
3419 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3423 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3424 throw INTERP_KERNEL::Exception(oss.str().c_str());
3427 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3428 int *connRetWork=connRet;
3429 std::set<INTERP_KERNEL::NormalizedCellType> types;
3430 for(const int *work=begin;work!=end;work++)
3432 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3433 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3436 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3438 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3439 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3441 ret->copyTinyInfoFrom(this);
3446 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3448 * For 1D cells, the returned field contains lengths.<br>
3449 * For 2D cells, the returned field contains areas.<br>
3450 * For 3D cells, the returned field contains volumes.
3451 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3452 * orientation, i.e. the volume is always positive.
3453 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3454 * and one time . The caller is to delete this field using decrRef() as it is no
3457 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3459 std::string name="MeasureOfMesh_";
3461 int nbelem=getNumberOfCells();
3462 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3463 field->setName(name);
3464 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3465 array->alloc(nbelem,1);
3466 double *area_vol=array->getPointer();
3467 field->setArray(array) ; array=0;
3468 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3469 field->synchronizeTimeWithMesh();
3470 if(getMeshDimension()!=-1)
3473 INTERP_KERNEL::NormalizedCellType type;
3474 int dim_space=getSpaceDimension();
3475 const double *coords=getCoords()->getConstPointer();
3476 const int *connec=getNodalConnectivity()->getConstPointer();
3477 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3478 for(int iel=0;iel<nbelem;iel++)
3480 ipt=connec_index[iel];
3481 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3482 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);
3485 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3489 area_vol[0]=std::numeric_limits<double>::max();
3491 return field.retn();
3495 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3497 * For 1D cells, the returned array contains lengths.<br>
3498 * For 2D cells, the returned array contains areas.<br>
3499 * For 3D cells, the returned array contains volumes.
3500 * This method avoids building explicitly a part of \a this mesh to perform the work.
3501 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3502 * orientation, i.e. the volume is always positive.
3503 * \param [in] begin - an array of cell ids of interest.
3504 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3505 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3506 * delete this array using decrRef() as it is no more needed.
3508 * \if ENABLE_EXAMPLES
3509 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3510 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3512 * \sa getMeasureField()
3514 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3516 std::string name="PartMeasureOfMesh_";
3518 int nbelem=(int)std::distance(begin,end);
3519 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3520 array->setName(name);
3521 array->alloc(nbelem,1);
3522 double *area_vol=array->getPointer();
3523 if(getMeshDimension()!=-1)
3526 INTERP_KERNEL::NormalizedCellType type;
3527 int dim_space=getSpaceDimension();
3528 const double *coords=getCoords()->getConstPointer();
3529 const int *connec=getNodalConnectivity()->getConstPointer();
3530 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3531 for(const int *iel=begin;iel!=end;iel++)
3533 ipt=connec_index[*iel];
3534 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3535 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3538 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3542 area_vol[0]=std::numeric_limits<double>::max();
3544 return array.retn();
3548 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3549 * \a this one. The returned field contains the dual cell volume for each corresponding
3550 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3551 * the dual mesh in P1 sens of \a this.<br>
3552 * For 1D cells, the returned field contains lengths.<br>
3553 * For 2D cells, the returned field contains areas.<br>
3554 * For 3D cells, the returned field contains volumes.
3555 * This method is useful to check "P1*" conservative interpolators.
3556 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3557 * orientation, i.e. the volume is always positive.
3558 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3559 * nodes and one time. The caller is to delete this array using decrRef() as
3560 * it is no more needed.
3562 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3564 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3565 std::string name="MeasureOnNodeOfMesh_";
3567 int nbNodes=getNumberOfNodes();
3568 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3569 double cst=1./((double)getMeshDimension()+1.);
3570 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3571 array->alloc(nbNodes,1);
3572 double *valsToFill=array->getPointer();
3573 std::fill(valsToFill,valsToFill+nbNodes,0.);
3574 const double *values=tmp->getArray()->getConstPointer();
3575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3577 getReverseNodalConnectivity(da,daInd);
3578 const int *daPtr=da->getConstPointer();
3579 const int *daIPtr=daInd->getConstPointer();
3580 for(int i=0;i<nbNodes;i++)
3581 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3582 valsToFill[i]+=cst*values[*cell];
3584 ret->setArray(array);
3589 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3590 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3591 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3592 * and are normalized.
3593 * <br> \a this can be either
3594 * - a 2D mesh in 2D or 3D space or
3595 * - an 1D mesh in 2D space.
3597 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3598 * cells and one time. The caller is to delete this field using decrRef() as
3599 * it is no more needed.
3600 * \throw If the nodal connectivity of cells is not defined.
3601 * \throw If the coordinates array is not set.
3602 * \throw If the mesh dimension is not set.
3603 * \throw If the mesh and space dimension is not as specified above.
3605 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3607 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3608 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3609 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3610 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3611 int nbOfCells=getNumberOfCells();
3612 int nbComp=getMeshDimension()+1;
3613 array->alloc(nbOfCells,nbComp);
3614 double *vals=array->getPointer();
3615 const int *connI=_nodal_connec_index->getConstPointer();
3616 const int *conn=_nodal_connec->getConstPointer();
3617 const double *coords=_coords->getConstPointer();
3618 if(getMeshDimension()==2)
3620 if(getSpaceDimension()==3)
3622 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3623 const double *locPtr=loc->getConstPointer();
3624 for(int i=0;i<nbOfCells;i++,vals+=3)
3626 int offset=connI[i];
3627 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3628 double n=INTERP_KERNEL::norm<3>(vals);
3629 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3634 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3635 const double *isAbsPtr=isAbs->getArray()->begin();
3636 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3637 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3640 else//meshdimension==1
3643 for(int i=0;i<nbOfCells;i++)
3645 int offset=connI[i];
3646 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3647 double n=INTERP_KERNEL::norm<2>(tmp);
3648 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3653 ret->setArray(array);
3655 ret->synchronizeTimeWithSupport();
3660 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3661 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3662 * and are normalized.
3663 * <br> \a this can be either
3664 * - a 2D mesh in 2D or 3D space or
3665 * - an 1D mesh in 2D space.
3667 * This method avoids building explicitly a part of \a this mesh to perform the work.
3668 * \param [in] begin - an array of cell ids of interest.
3669 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3670 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3671 * cells and one time. The caller is to delete this field using decrRef() as
3672 * it is no more needed.
3673 * \throw If the nodal connectivity of cells is not defined.
3674 * \throw If the coordinates array is not set.
3675 * \throw If the mesh dimension is not set.
3676 * \throw If the mesh and space dimension is not as specified above.
3677 * \sa buildOrthogonalField()
3679 * \if ENABLE_EXAMPLES
3680 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3681 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3684 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3686 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3687 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3688 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3689 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3690 std::size_t nbelems=std::distance(begin,end);
3691 int nbComp=getMeshDimension()+1;
3692 array->alloc((int)nbelems,nbComp);
3693 double *vals=array->getPointer();
3694 const int *connI=_nodal_connec_index->getConstPointer();
3695 const int *conn=_nodal_connec->getConstPointer();
3696 const double *coords=_coords->getConstPointer();
3697 if(getMeshDimension()==2)
3699 if(getSpaceDimension()==3)
3701 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3702 const double *locPtr=loc->getConstPointer();
3703 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3705 int offset=connI[*i];
3706 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3707 double n=INTERP_KERNEL::norm<3>(vals);
3708 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3713 for(std::size_t i=0;i<nbelems;i++)
3714 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3717 else//meshdimension==1
3720 for(const int *i=begin;i!=end;i++)
3722 int offset=connI[*i];
3723 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3724 double n=INTERP_KERNEL::norm<2>(tmp);
3725 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3730 ret->setArray(array);
3732 ret->synchronizeTimeWithSupport();
3737 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3738 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3739 * and are \b not normalized.
3740 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3741 * cells and one time. The caller is to delete this field using decrRef() as
3742 * it is no more needed.
3743 * \throw If the nodal connectivity of cells is not defined.
3744 * \throw If the coordinates array is not set.
3745 * \throw If \a this->getMeshDimension() != 1.
3746 * \throw If \a this mesh includes cells of type other than SEG2.
3748 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3750 if(getMeshDimension()!=1)
3751 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3752 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3753 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3755 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3756 int nbOfCells=getNumberOfCells();
3757 int spaceDim=getSpaceDimension();
3758 array->alloc(nbOfCells,spaceDim);
3759 double *pt=array->getPointer();
3760 const double *coo=getCoords()->getConstPointer();
3761 std::vector<int> conn;
3763 for(int i=0;i<nbOfCells;i++)
3766 getNodeIdsOfCell(i,conn);
3767 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3769 ret->setArray(array);
3771 ret->synchronizeTimeWithSupport();
3776 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3777 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3778 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3779 * from. If a result face is shared by two 3D cells, then the face in included twice in
3781 * \param [in] origin - 3 components of a point defining location of the plane.
3782 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3783 * must be greater than 1e-6.
3784 * \param [in] eps - half-thickness of the plane.
3785 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3786 * producing correspondent 2D cells. The caller is to delete this array
3787 * using decrRef() as it is no more needed.
3788 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3789 * not share the node coordinates array with \a this mesh. The caller is to
3790 * delete this mesh using decrRef() as it is no more needed.
3791 * \throw If the coordinates array is not set.
3792 * \throw If the nodal connectivity of cells is not defined.
3793 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3794 * \throw If magnitude of \a vec is less than 1e-6.
3795 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3796 * \throw If \a this includes quadratic cells.
3798 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3800 checkFullyDefined();
3801 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3802 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3804 if(candidates->empty())
3805 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3806 std::vector<int> nodes;
3807 DataArrayInt *cellIds1D=0;
3808 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3809 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3814 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3815 revDesc2=0; revDescIndx2=0;
3816 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3817 revDesc1=0; revDescIndx1=0;
3818 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3821 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3822 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3824 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3825 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3826 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3827 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3828 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3830 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3831 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3832 if(cellIds2->empty())
3833 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3834 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3835 ret->setCoords(mDesc1->getCoords());
3836 ret->setConnectivity(conn,connI,true);
3837 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3842 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3843 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
3844 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3846 * \param [in] origin - 3 components of a point defining location of the plane.
3847 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3848 * must be greater than 1e-6.
3849 * \param [in] eps - half-thickness of the plane.
3850 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3851 * producing correspondent segments. The caller is to delete this array
3852 * using decrRef() as it is no more needed.
3853 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3854 * mesh in 3D space. This mesh does not share the node coordinates array with
3855 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3857 * \throw If the coordinates array is not set.
3858 * \throw If the nodal connectivity of cells is not defined.
3859 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3860 * \throw If magnitude of \a vec is less than 1e-6.
3861 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3862 * \throw If \a this includes quadratic cells.
3864 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3866 checkFullyDefined();
3867 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3869 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3870 if(candidates->empty())
3871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3872 std::vector<int> nodes;
3873 DataArrayInt *cellIds1D=0;
3874 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3875 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3880 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3881 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3884 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3885 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3887 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3888 int ncellsSub=subMesh->getNumberOfCells();
3889 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3890 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3891 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3892 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3895 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3896 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3897 for(int i=0;i<ncellsSub;i++)
3899 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3901 if(cut3DSurf[i].first!=-2)
3903 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3904 connI->pushBackSilent(conn->getNumberOfTuples());
3905 cellIds2->pushBackSilent(i);
3909 int cellId3DSurf=cut3DSurf[i].second;
3910 int offset=nodalI[cellId3DSurf]+1;
3911 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3912 for(int j=0;j<nbOfEdges;j++)
3914 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3915 connI->pushBackSilent(conn->getNumberOfTuples());
3916 cellIds2->pushBackSilent(cellId3DSurf);
3921 if(cellIds2->empty())
3922 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3923 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3924 ret->setCoords(mDesc1->getCoords());
3925 ret->setConnectivity(conn,connI,true);
3926 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3931 * Finds cells whose bounding boxes intersect a given plane.
3932 * \param [in] origin - 3 components of a point defining location of the plane.
3933 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3934 * must be greater than 1e-6.
3935 * \param [in] eps - half-thickness of the plane.
3936 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3937 * cells. The caller is to delete this array using decrRef() as it is no more
3939 * \throw If the coordinates array is not set.
3940 * \throw If the nodal connectivity of cells is not defined.
3941 * \throw If \a this->getSpaceDimension() != 3.
3942 * \throw If magnitude of \a vec is less than 1e-6.
3943 * \sa buildSlice3D()
3945 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3947 checkFullyDefined();
3948 if(getSpaceDimension()!=3)
3949 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3950 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3952 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3954 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3955 double angle=acos(vec[2]/normm);
3956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3960 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3961 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3962 if(normm2/normm>1e-6)
3963 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3964 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3966 mw->getBoundingBox(bbox);
3967 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3968 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3972 getBoundingBox(bbox);
3973 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3974 cellIds=getCellsInBoundingBox(bbox,eps);
3976 return cellIds.retn();
3980 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3981 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3982 * No consideration of coordinate is done by this method.
3983 * 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)
3984 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3986 bool MEDCouplingUMesh::isContiguous1D() const
3988 if(getMeshDimension()!=1)
3989 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3990 int nbCells=getNumberOfCells();
3992 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3993 const int *connI=_nodal_connec_index->getConstPointer();
3994 const int *conn=_nodal_connec->getConstPointer();
3995 int ref=conn[connI[0]+2];
3996 for(int i=1;i<nbCells;i++)
3998 if(conn[connI[i]+1]!=ref)
4000 ref=conn[connI[i]+2];
4006 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4007 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4008 * \param pt reference point of the line
4009 * \param v normalized director vector of the line
4010 * \param eps max precision before throwing an exception
4011 * \param res output of size this->getNumberOfCells
4013 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4015 if(getMeshDimension()!=1)
4016 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4017 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4018 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4019 if(getSpaceDimension()!=3)
4020 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4021 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4022 const double *fPtr=f->getArray()->getConstPointer();
4024 for(int i=0;i<getNumberOfCells();i++)
4026 const double *tmp1=fPtr+3*i;
4027 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4028 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4029 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4030 double n1=INTERP_KERNEL::norm<3>(tmp);
4031 n1/=INTERP_KERNEL::norm<3>(tmp1);
4033 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4035 const double *coo=getCoords()->getConstPointer();
4036 for(int i=0;i<getNumberOfNodes();i++)
4038 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4039 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4040 res[i]=std::accumulate(tmp,tmp+3,0.);
4045 * 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.
4046 * \a this is expected to be a mesh so that its space dimension is equal to its
4047 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4048 * 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).
4050 * 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
4051 * 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).
4052 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4054 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4055 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4057 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4058 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4059 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4060 * \return the positive value of the distance.
4061 * \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
4063 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4065 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4067 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4068 if(meshDim!=spaceDim-1)
4069 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4070 if(meshDim!=2 && meshDim!=1)
4071 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4072 checkFullyDefined();
4073 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4074 { 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()); }
4075 DataArrayInt *ret1=0;
4076 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4077 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4078 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4079 cellId=*ret1Safe->begin();
4080 return *ret0->begin();
4084 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4085 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4086 * 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
4087 * 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).
4088 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4090 * \a this is expected to be a mesh so that its space dimension is equal to its
4091 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4092 * 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).
4094 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4095 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4097 * \param [in] pts the list of points in which each tuple represents a point
4098 * \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.
4099 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4100 * \throw if number of components of \a pts is not equal to the space dimension.
4101 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4102 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4104 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4107 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4108 pts->checkAllocated();
4109 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4110 if(meshDim!=spaceDim-1)
4111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4112 if(meshDim!=2 && meshDim!=1)
4113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4114 if(pts->getNumberOfComponents()!=spaceDim)
4116 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4117 throw INTERP_KERNEL::Exception(oss.str().c_str());
4119 checkFullyDefined();
4120 int nbCells=getNumberOfCells();
4122 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4123 int nbOfPts=pts->getNumberOfTuples();
4124 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4126 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4127 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4128 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4129 const double *bbox(bboxArr->begin());
4134 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4135 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4137 double x=std::numeric_limits<double>::max();
4138 std::vector<int> elems;
4139 myTree.getMinDistanceOfMax(ptsPtr,x);
4140 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4141 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4147 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4148 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4150 double x=std::numeric_limits<double>::max();
4151 std::vector<int> elems;
4152 myTree.getMinDistanceOfMax(ptsPtr,x);
4153 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4154 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4159 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4161 cellIds=ret1.retn();
4168 * \param [in] pt the start pointer (included) of the coordinates of the point
4169 * \param [in] cellIdsBg the start pointer (included) of cellIds
4170 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4171 * \param [in] nc nodal connectivity
4172 * \param [in] ncI nodal connectivity index
4173 * \param [in,out] ret0 the min distance between \a this and the external input point
4174 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4175 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4177 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)
4180 ret0=std::numeric_limits<double>::max();
4181 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4183 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4185 case INTERP_KERNEL::NORM_TRI3:
4187 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4189 { ret0=tmp; cellId=*zeCell; }
4192 case INTERP_KERNEL::NORM_QUAD4:
4193 case INTERP_KERNEL::NORM_POLYGON:
4195 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4197 { ret0=tmp; cellId=*zeCell; }
4201 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4207 * \param [in] pt the start pointer (included) of the coordinates of the point
4208 * \param [in] cellIdsBg the start pointer (included) of cellIds
4209 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4210 * \param [in] nc nodal connectivity
4211 * \param [in] ncI nodal connectivity index
4212 * \param [in,out] ret0 the min distance between \a this and the external input point
4213 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4214 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4216 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)
4219 ret0=std::numeric_limits<double>::max();
4220 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4222 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4224 case INTERP_KERNEL::NORM_SEG2:
4226 std::size_t uselessEntry=0;
4227 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4230 { ret0=tmp; cellId=*zeCell; }
4234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4241 * Finds cells in contact with a ball (i.e. a point with precision).
4242 * 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.
4243 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4245 * \warning This method is suitable if the caller intends to evaluate only one
4246 * point, for more points getCellsContainingPoints() is recommended as it is
4248 * \param [in] pos - array of coordinates of the ball central point.
4249 * \param [in] eps - ball radius.
4250 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4251 * if there are no such cells.
4252 * \throw If the coordinates array is not set.
4253 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4255 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4257 std::vector<int> elts;
4258 getCellsContainingPoint(pos,eps,elts);
4261 return elts.front();
4265 * Finds cells in contact with a ball (i.e. a point with precision).
4266 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4267 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4268 * \warning This method is suitable if the caller intends to evaluate only one
4269 * point, for more points getCellsContainingPoints() is recommended as it is
4271 * \param [in] pos - array of coordinates of the ball central point.
4272 * \param [in] eps - ball radius.
4273 * \param [out] elts - vector returning ids of the found cells. It is cleared
4274 * before inserting ids.
4275 * \throw If the coordinates array is not set.
4276 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4278 * \if ENABLE_EXAMPLES
4279 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4280 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4283 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4286 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4287 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4292 namespace ParaMEDMEM
4294 template<const int SPACEDIMM>
4298 static const int MY_SPACEDIM=SPACEDIMM;
4299 static const int MY_MESHDIM=8;
4300 typedef int MyConnType;
4301 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4303 // useless, but for windows compilation ...
4304 const double* getCoordinatesPtr() const { return 0; }
4305 const int* getConnectivityPtr() const { return 0; }
4306 const int* getConnectivityIndexPtr() const { return 0; }
4307 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4311 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4313 INTERP_KERNEL::Edge *ret(0);
4314 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]));
4315 m[n0]=bg[0]; m[n1]=bg[1];
4318 case INTERP_KERNEL::NORM_SEG2:
4320 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4323 case INTERP_KERNEL::NORM_SEG3:
4325 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4326 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4327 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4328 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4329 bool colinearity(inters.areColinears());
4330 delete e1; delete e2;
4332 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4334 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4338 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4343 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4345 INTERP_KERNEL::Edge *ret=0;
4348 case INTERP_KERNEL::NORM_SEG2:
4350 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4353 case INTERP_KERNEL::NORM_SEG3:
4355 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4356 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4357 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4358 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4359 bool colinearity=inters.areColinears();
4360 delete e1; delete e2;
4362 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4364 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4365 mapp2[bg[2]].second=false;
4369 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4375 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4376 * the global mesh 'mDesc'.
4377 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4378 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4380 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4381 std::map<INTERP_KERNEL::Node *,int>& mapp)
4384 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.
4385 const double *coo=mDesc->getCoords()->getConstPointer();
4386 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4387 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4389 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4390 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4391 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4393 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4394 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4396 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4397 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4399 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4400 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4402 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4404 if((*it2).second.second)
4405 mapp[(*it2).second.first]=(*it2).first;
4406 ((*it2).second.first)->decrRef();
4411 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4415 int locId=nodeId-offset2;
4416 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4420 int locId=nodeId-offset1;
4421 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4423 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4427 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4429 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4430 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4431 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4433 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4435 int eltId1=abs(*desc1)-1;
4436 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4438 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4439 if(it==mappRev.end())
4441 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4452 template<int SPACEDIM>
4453 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4454 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4456 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4457 int *eltsIndexPtr(eltsIndex->getPointer());
4458 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4459 const double *bbox(bboxArr->begin());
4460 int nbOfCells=getNumberOfCells();
4461 const int *conn=_nodal_connec->getConstPointer();
4462 const int *connI=_nodal_connec_index->getConstPointer();
4463 double bb[2*SPACEDIM];
4464 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4465 for(int i=0;i<nbOfPoints;i++)
4467 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4468 for(int j=0;j<SPACEDIM;j++)
4470 bb[2*j]=pos[SPACEDIM*i+j];
4471 bb[2*j+1]=pos[SPACEDIM*i+j];
4473 std::vector<int> candidates;
4474 myTree.getIntersectingElems(bb,candidates);
4475 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4477 int sz(connI[(*iter)+1]-connI[*iter]-1);
4478 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4480 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4481 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4485 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4486 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4487 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4488 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4489 INTERP_KERNEL::QuadraticPolygon *pol(0);
4490 for(int j=0;j<sz;j++)
4492 int nodeId(conn[connI[*iter]+1+j]);
4493 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4495 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4496 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4498 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4499 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4500 double a(0.),b(0.),c(0.);
4501 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4502 status=pol->isInOrOut2(n);
4503 delete pol; n->decrRef();
4507 eltsIndexPtr[i+1]++;
4508 elts->pushBackSilent(*iter);
4514 * Finds cells in contact with several balls (i.e. points with precision).
4515 * This method is an extension of getCellContainingPoint() and
4516 * getCellsContainingPoint() for the case of multiple points.
4517 * 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.
4518 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4519 * \param [in] pos - an array of coordinates of points in full interlace mode :
4520 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4521 * this->getSpaceDimension() * \a nbOfPoints
4522 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4523 * \param [in] eps - radius of balls (i.e. the precision).
4524 * \param [out] elts - vector returning ids of found cells.
4525 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4526 * dividing cell ids in \a elts into groups each referring to one
4527 * point. Its every element (except the last one) is an index pointing to the
4528 * first id of a group of cells. For example cells in contact with the *i*-th
4529 * point are described by following range of indices:
4530 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4531 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4532 * Number of cells in contact with the *i*-th point is
4533 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4534 * \throw If the coordinates array is not set.
4535 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4537 * \if ENABLE_EXAMPLES
4538 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4539 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4542 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4543 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4545 int spaceDim=getSpaceDimension();
4546 int mDim=getMeshDimension();
4551 const double *coords=_coords->getConstPointer();
4552 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4559 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4561 else if(spaceDim==2)
4565 const double *coords=_coords->getConstPointer();
4566 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4569 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4571 else if(spaceDim==1)
4575 const double *coords=_coords->getConstPointer();
4576 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4579 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4586 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4587 * least two its edges intersect each other anywhere except their extremities. An
4588 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4589 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4590 * cleared before filling in.
4591 * \param [in] eps - precision.
4592 * \throw If \a this->getMeshDimension() != 2.
4593 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4595 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4597 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4598 if(getMeshDimension()!=2)
4599 throw INTERP_KERNEL::Exception(msg);
4600 int spaceDim=getSpaceDimension();
4601 if(spaceDim!=2 && spaceDim!=3)
4602 throw INTERP_KERNEL::Exception(msg);
4603 const int *conn=_nodal_connec->getConstPointer();
4604 const int *connI=_nodal_connec_index->getConstPointer();
4605 int nbOfCells=getNumberOfCells();
4606 std::vector<double> cell2DinS2;
4607 for(int i=0;i<nbOfCells;i++)
4609 int offset=connI[i];
4610 int nbOfNodesForCell=connI[i+1]-offset-1;
4611 if(nbOfNodesForCell<=3)
4613 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4614 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4615 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4622 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4624 * 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.
4625 * 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.
4627 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4628 * This convex envelop is computed using Jarvis march algorithm.
4629 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4630 * 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)
4631 * 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.
4633 * \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.
4634 * \sa MEDCouplingUMesh::colinearize2D
4636 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4638 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4639 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4640 checkFullyDefined();
4641 const double *coords=getCoords()->getConstPointer();
4642 int nbOfCells=getNumberOfCells();
4643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4644 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4646 int *workIndexOut=nodalConnecIndexOut->getPointer();
4648 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4649 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4650 std::set<INTERP_KERNEL::NormalizedCellType> types;
4651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4652 isChanged->alloc(0,1);
4653 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4655 int pos=nodalConnecOut->getNumberOfTuples();
4656 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4657 isChanged->pushBackSilent(i);
4658 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4659 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4661 if(isChanged->empty())
4663 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4665 return isChanged.retn();
4669 * This method is \b NOT const because it can modify \a this.
4670 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4671 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4672 * \param policy specifies the type of extrusion chosen:
4673 * - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4674 * will be repeated to build each level
4675 * - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4676 * the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4677 * along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4679 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4681 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4683 checkFullyDefined();
4684 mesh1D->checkFullyDefined();
4685 if(!mesh1D->isContiguous1D())
4686 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4687 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4688 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4689 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4690 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4691 if(mesh1D->getMeshDimension()!=1)
4692 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4694 if(isPresenceOfQuadratic())
4696 if(mesh1D->isFullyQuadratic())
4699 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4701 int oldNbOfNodes(getNumberOfNodes());
4702 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4707 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4712 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4716 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4718 setCoords(newCoords);
4719 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4725 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4726 * If it is not the case an exception will be thrown.
4727 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4728 * intersection of plane defined by ('origin','vec').
4729 * This method has one in/out parameter : 'cut3DCurve'.
4730 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4731 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4732 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4733 * This method will throw an exception if \a this contains a non linear segment.
4735 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4737 checkFullyDefined();
4738 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4739 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4740 int ncells=getNumberOfCells();
4741 int nnodes=getNumberOfNodes();
4742 double vec2[3],vec3[3],vec4[3];
4743 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4746 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4747 const int *conn=_nodal_connec->getConstPointer();
4748 const int *connI=_nodal_connec_index->getConstPointer();
4749 const double *coo=_coords->getConstPointer();
4750 std::vector<double> addCoo;
4751 for(int i=0;i<ncells;i++)
4753 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4755 if(cut3DCurve[i]==-2)
4757 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4758 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];
4759 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4760 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4761 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4763 const double *st2=coo+3*st;
4764 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4765 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]));
4766 if(pos>eps && pos<1-eps)
4768 int nNode=((int)addCoo.size())/3;
4769 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4770 addCoo.insert(addCoo.end(),vec4,vec4+3);
4771 cut3DCurve[i]=nnodes+nNode;
4777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4781 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4782 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4783 coo2->alloc(newNbOfNodes,3);
4784 double *tmp=coo2->getPointer();
4785 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4786 std::copy(addCoo.begin(),addCoo.end(),tmp);
4787 DataArrayDouble::SetArrayIn(coo2,_coords);
4792 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4793 * \param mesh1D is the input 1D mesh used for translation computation.
4794 * \return newCoords new coords filled by this method.
4796 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4798 int oldNbOfNodes=getNumberOfNodes();
4799 int nbOf1DCells=mesh1D->getNumberOfCells();
4800 int spaceDim=getSpaceDimension();
4801 DataArrayDouble *ret=DataArrayDouble::New();
4802 std::vector<bool> isQuads;
4803 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4804 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4805 double *retPtr=ret->getPointer();
4806 const double *coords=getCoords()->getConstPointer();
4807 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4809 std::vector<double> c;
4813 for(int i=0;i<nbOf1DCells;i++)
4816 mesh1D->getNodeIdsOfCell(i,v);
4818 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4819 mesh1D->getCoordinatesOfNode(v[0],c);
4820 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4821 for(int j=0;j<oldNbOfNodes;j++)
4822 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4826 mesh1D->getCoordinatesOfNode(v[1],c);
4827 mesh1D->getCoordinatesOfNode(v[0],c);
4828 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4829 for(int j=0;j<oldNbOfNodes;j++)
4830 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4833 ret->copyStringInfoFrom(*getCoords());
4838 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4839 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4840 * \return newCoords new coords filled by this method.
4842 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4844 if(mesh1D->getSpaceDimension()==2)
4845 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4846 if(mesh1D->getSpaceDimension()==3)
4847 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4848 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4852 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4853 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4854 * \return newCoords new coords filled by this method.
4856 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4860 int oldNbOfNodes=getNumberOfNodes();
4861 int nbOf1DCells=mesh1D->getNumberOfCells();
4863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4864 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4865 int nbOfLevsInVec=nbOf1DCells+1;
4866 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4867 double *retPtr=ret->getPointer();
4868 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4869 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4870 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4871 tmp->setCoords(tmp2);
4872 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4873 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4874 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4875 for(int i=1;i<nbOfLevsInVec;i++)
4877 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4878 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4879 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4880 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4881 tmp->translate(vec);
4882 double tmp3[2],radius,alpha,alpha0;
4883 const double *p0=i+1<nbOfLevsInVec?begin:third;
4884 const double *p1=i+1<nbOfLevsInVec?end:begin;
4885 const double *p2=i+1<nbOfLevsInVec?third:end;
4886 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4887 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]);
4888 double angle=acos(cosangle/(radius*radius));
4889 tmp->rotate(end,0,angle);
4890 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4896 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4897 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4898 * \return newCoords new coords filled by this method.
4900 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4904 int oldNbOfNodes=getNumberOfNodes();
4905 int nbOf1DCells=mesh1D->getNumberOfCells();
4907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4908 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4909 int nbOfLevsInVec=nbOf1DCells+1;
4910 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4911 double *retPtr=ret->getPointer();
4912 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4913 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4914 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4915 tmp->setCoords(tmp2);
4916 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4917 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4918 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4919 for(int i=1;i<nbOfLevsInVec;i++)
4921 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4922 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4923 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4924 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4925 tmp->translate(vec);
4926 double tmp3[2],radius,alpha,alpha0;
4927 const double *p0=i+1<nbOfLevsInVec?begin:third;
4928 const double *p1=i+1<nbOfLevsInVec?end:begin;
4929 const double *p2=i+1<nbOfLevsInVec?third:end;
4930 double vecPlane[3]={
4931 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4932 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4933 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4935 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4938 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4939 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4940 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4942 double c2=cos(asin(s2));
4944 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4945 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4946 {-vec2[1]*s2, vec2[0]*s2, c2}
4948 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]};
4949 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]};
4950 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]};
4951 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4952 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]);
4953 double angle=acos(cosangle/(radius*radius));
4954 tmp->rotate(end,vecPlane,angle);
4956 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4962 * This method is private because not easy to use for end user. This method is const contrary to
4963 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4964 * the coords sorted slice by slice.
4965 * \param isQuad specifies presence of quadratic cells.
4967 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4969 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4970 int nbOf2DCells(getNumberOfCells());
4971 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4972 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4973 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4975 newConnI->alloc(nbOf3DCells+1,1);
4976 int *newConnIPtr(newConnI->getPointer());
4978 std::vector<int> newc;
4979 for(int j=0;j<nbOf2DCells;j++)
4981 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4982 *newConnIPtr++=(int)newc.size();
4984 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4985 int *newConnPtr(newConn->getPointer());
4986 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4987 newConnIPtr=newConnI->getPointer();
4988 for(int iz=0;iz<nbOf1DCells;iz++)
4991 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4992 const int *posOfTypeOfCell(newConnIPtr);
4993 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4995 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4996 if(icell!=*posOfTypeOfCell)
4999 *newConnPtr=(*iter)+iz*deltaPerLev;
5010 ret->setConnectivity(newConn,newConnI,true);
5011 ret->setCoords(getCoords());
5016 * Checks if \a this mesh is constituted by only quadratic cells.
5017 * \return bool - \c true if there are only quadratic cells in \a this mesh.
5018 * \throw If the coordinates array is not set.
5019 * \throw If the nodal connectivity of cells is not defined.
5021 bool MEDCouplingUMesh::isFullyQuadratic() const
5023 checkFullyDefined();
5025 int nbOfCells=getNumberOfCells();
5026 for(int i=0;i<nbOfCells && ret;i++)
5028 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5029 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5030 ret=cm.isQuadratic();
5036 * Checks if \a this mesh includes any quadratic cell.
5037 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5038 * \throw If the coordinates array is not set.
5039 * \throw If the nodal connectivity of cells is not defined.
5041 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5043 checkFullyDefined();
5045 int nbOfCells=getNumberOfCells();
5046 for(int i=0;i<nbOfCells && !ret;i++)
5048 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5049 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5050 ret=cm.isQuadratic();
5056 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5057 * this mesh, it remains unchanged.
5058 * \throw If the coordinates array is not set.
5059 * \throw If the nodal connectivity of cells is not defined.
5061 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5063 checkFullyDefined();
5064 int nbOfCells=getNumberOfCells();
5066 const int *iciptr=_nodal_connec_index->getConstPointer();
5067 for(int i=0;i<nbOfCells;i++)
5069 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5070 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5071 if(cm.isQuadratic())
5073 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5074 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5075 if(!cml.isDynamic())
5076 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5078 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5084 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5085 const int *icptr=_nodal_connec->getConstPointer();
5086 newConn->alloc(getMeshLength()-delta,1);
5087 newConnI->alloc(nbOfCells+1,1);
5088 int *ocptr=newConn->getPointer();
5089 int *ociptr=newConnI->getPointer();
5092 for(int i=0;i<nbOfCells;i++,ociptr++)
5094 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5095 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5096 if(!cm.isQuadratic())
5098 _types.insert(type);
5099 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5100 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5104 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5105 _types.insert(typel);
5106 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5107 int newNbOfNodes=cml.getNumberOfNodes();
5109 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5110 *ocptr++=(int)typel;
5111 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5112 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5115 setConnectivity(newConn,newConnI,false);
5119 * This method converts all linear cell in \a this to quadratic one.
5120 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5121 * 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)
5122 * 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.
5123 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5124 * end of the existing coordinates.
5126 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5127 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5128 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5130 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5132 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5134 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5136 DataArrayInt *conn=0,*connI=0;
5137 DataArrayDouble *coords=0;
5138 std::set<INTERP_KERNEL::NormalizedCellType> types;
5139 checkFullyDefined();
5140 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5141 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5142 int meshDim=getMeshDimension();
5143 switch(conversionType)
5149 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5150 connSafe=conn; connISafe=connI; coordsSafe=coords;
5153 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5154 connSafe=conn; connISafe=connI; coordsSafe=coords;
5157 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5158 connSafe=conn; connISafe=connI; coordsSafe=coords;
5161 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5169 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5170 connSafe=conn; connISafe=connI; coordsSafe=coords;
5173 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5174 connSafe=conn; connISafe=connI; coordsSafe=coords;
5177 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5178 connSafe=conn; connISafe=connI; coordsSafe=coords;
5181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5188 setConnectivity(connSafe,connISafe,false);
5190 setCoords(coordsSafe);
5196 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5197 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5198 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5199 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5200 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5201 * This method can be seen as the opposite method of colinearize2D.
5202 * 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
5203 * to avoid to modify the numbering of existing nodes.
5205 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5206 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5207 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5208 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5209 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5210 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5211 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5213 * \sa buildDescendingConnectivity2
5215 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5216 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5218 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5219 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5220 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5221 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5222 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5223 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5224 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5225 //DataArrayInt *out0(0),*outi0(0);
5226 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5227 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5228 //out0s=out0s->buildUnique(); out0s->sort(true);
5233 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5234 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5235 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5237 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5239 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5243 int nbOfCells=getNumberOfCells();
5244 int nbOfNodes=getNumberOfNodes();
5245 const int *cPtr=_nodal_connec->getConstPointer();
5246 const int *icPtr=_nodal_connec_index->getConstPointer();
5247 int lastVal=0,offset=nbOfNodes;
5248 for(int i=0;i<nbOfCells;i++,icPtr++)
5250 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5251 if(type==INTERP_KERNEL::NORM_SEG2)
5253 types.insert(INTERP_KERNEL::NORM_SEG3);
5254 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5255 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5256 newConn->pushBackSilent(offset++);
5258 newConnI->pushBackSilent(lastVal);
5259 ret->pushBackSilent(i);
5264 lastVal+=(icPtr[1]-icPtr[0]);
5265 newConnI->pushBackSilent(lastVal);
5266 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5269 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5270 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5274 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
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5280 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5281 DataArrayInt *conn1D=0,*conn1DI=0;
5282 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5283 DataArrayDouble *coordsTmp=0;
5284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5285 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5287 const int *c1DPtr=conn1D->begin();
5288 const int *c1DIPtr=conn1DI->begin();
5289 int nbOfCells=getNumberOfCells();
5290 const int *cPtr=_nodal_connec->getConstPointer();
5291 const int *icPtr=_nodal_connec_index->getConstPointer();
5293 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5295 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5296 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5297 if(!cm.isQuadratic())
5299 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5300 types.insert(typ2); newConn->pushBackSilent(typ2);
5301 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5302 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5303 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5304 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5305 newConnI->pushBackSilent(lastVal);
5306 ret->pushBackSilent(i);
5311 lastVal+=(icPtr[1]-icPtr[0]);
5312 newConnI->pushBackSilent(lastVal);
5313 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5316 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5321 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5322 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5323 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5325 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5328 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5329 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5332 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5335 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5341 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5342 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5343 DataArrayInt *conn1D=0,*conn1DI=0;
5344 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5345 DataArrayDouble *coordsTmp=0;
5346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5349 const int *c1DPtr=conn1D->begin();
5350 const int *c1DIPtr=conn1DI->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++)
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 types.insert(typ2); newConn->pushBackSilent(typ2);
5363 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5364 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5365 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5366 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5367 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5368 newConnI->pushBackSilent(lastVal);
5369 ret->pushBackSilent(i);
5374 lastVal+=(icPtr[1]-icPtr[0]);
5375 newConnI->pushBackSilent(lastVal);
5376 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5379 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5380 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5385 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5386 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5387 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5389 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5393 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5396 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5399 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5407 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5408 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5409 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5410 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5411 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5414 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5415 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5416 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5418 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5419 int nbOfCells=getNumberOfCells();
5420 const int *cPtr=_nodal_connec->getConstPointer();
5421 const int *icPtr=_nodal_connec_index->getConstPointer();
5422 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5423 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5425 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5426 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5427 if(!cm.isQuadratic())
5429 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5430 if(typ2==INTERP_KERNEL::NORM_ERROR)
5432 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5433 throw INTERP_KERNEL::Exception(oss.str().c_str());
5435 types.insert(typ2); newConn->pushBackSilent(typ2);
5436 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5437 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5438 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5439 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5441 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5442 int tmpPos=newConn->getNumberOfTuples();
5443 newConn->pushBackSilent(nodeId2);
5444 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5446 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5447 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5448 newConnI->pushBackSilent(lastVal);
5449 ret->pushBackSilent(i);
5454 lastVal+=(icPtr[1]-icPtr[0]);
5455 newConnI->pushBackSilent(lastVal);
5456 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5461 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5462 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5463 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5464 int *c=newConn->getPointer();
5465 const int *cI(newConnI->begin());
5466 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5467 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5468 offset=coordsTmp2Safe->getNumberOfTuples();
5469 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5470 c[cI[(*elt)+1]-1]+=offset;
5471 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5476 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5477 * so that the number of cells remains the same. Quadratic faces are converted to
5478 * polygons. This method works only for 2D meshes in
5479 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5480 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5481 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5482 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5483 * a polylinized edge constituting the input polygon.
5484 * \throw If the coordinates array is not set.
5485 * \throw If the nodal connectivity of cells is not defined.
5486 * \throw If \a this->getMeshDimension() != 2.
5487 * \throw If \a this->getSpaceDimension() != 2.
5489 void MEDCouplingUMesh::tessellate2D(double eps)
5491 checkFullyDefined();
5492 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5493 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5494 double epsa=fabs(eps);
5495 if(epsa<std::numeric_limits<double>::min())
5496 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 !");
5497 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5498 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5499 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5500 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5501 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5502 revDesc1=0; revDescIndx1=0;
5503 mDesc->tessellate2DCurve(eps);
5504 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5505 setCoords(mDesc->getCoords());
5509 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5510 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5511 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5512 * a sub-divided edge.
5513 * \throw If the coordinates array is not set.
5514 * \throw If the nodal connectivity of cells is not defined.
5515 * \throw If \a this->getMeshDimension() != 1.
5516 * \throw If \a this->getSpaceDimension() != 2.
5518 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5520 checkFullyDefined();
5521 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5522 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5523 double epsa=fabs(eps);
5524 if(epsa<std::numeric_limits<double>::min())
5525 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 !");
5526 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5527 int nbCells=getNumberOfCells();
5528 int nbNodes=getNumberOfNodes();
5529 const int *conn=_nodal_connec->getConstPointer();
5530 const int *connI=_nodal_connec_index->getConstPointer();
5531 const double *coords=_coords->getConstPointer();
5532 std::vector<double> addCoo;
5533 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5535 newConnI->alloc(nbCells+1,1);
5536 int *newConnIPtr=newConnI->getPointer();
5539 INTERP_KERNEL::Node *tmp2[3];
5540 std::set<INTERP_KERNEL::NormalizedCellType> types;
5541 for(int i=0;i<nbCells;i++,newConnIPtr++)
5543 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5544 if(cm.isQuadratic())
5545 {//assert(connI[i+1]-connI[i]-1==3)
5546 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5547 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5548 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5549 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5550 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5553 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5554 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5556 newConnIPtr[1]=(int)newConn.size();
5560 types.insert(INTERP_KERNEL::NORM_SEG2);
5561 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5562 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5563 newConnIPtr[1]=newConnIPtr[0]+3;
5568 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5569 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5570 newConnIPtr[1]=newConnIPtr[0]+3;
5573 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5576 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5577 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5578 newConnArr->alloc((int)newConn.size(),1);
5579 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5580 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5581 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5582 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5583 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5584 std::copy(addCoo.begin(),addCoo.end(),work);
5585 DataArrayDouble::SetArrayIn(newCoords,_coords);
5590 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5591 * In addition, returns an array mapping new cells to old ones. <br>
5592 * This method typically increases the number of cells in \a this mesh
5593 * but the number of nodes remains \b unchanged.
5594 * That's why the 3D splitting policies
5595 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5596 * \param [in] policy - specifies a pattern used for splitting.
5597 * The semantic of \a policy is:
5598 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5599 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5600 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5601 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5604 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5605 * an id of old cell producing it. The caller is to delete this array using
5606 * decrRef() as it is no more needed.
5608 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5609 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5610 * and \a this->getMeshDimension() != 3.
5611 * \throw If \a policy is not one of the four discussed above.
5612 * \throw If the nodal connectivity of cells is not defined.
5613 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5615 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5620 return simplexizePol0();
5622 return simplexizePol1();
5623 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5624 return simplexizePlanarFace5();
5625 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5626 return simplexizePlanarFace6();
5628 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)");
5633 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5634 * - 1D: INTERP_KERNEL::NORM_SEG2
5635 * - 2D: INTERP_KERNEL::NORM_TRI3
5636 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5638 * This method is useful for users that need to use P1 field services as
5639 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5640 * All these methods need mesh support containing only simplex cells.
5641 * \return bool - \c true if there are only simplex cells in \a this mesh.
5642 * \throw If the coordinates array is not set.
5643 * \throw If the nodal connectivity of cells is not defined.
5644 * \throw If \a this->getMeshDimension() < 1.
5646 bool MEDCouplingUMesh::areOnlySimplexCells() const
5648 checkFullyDefined();
5649 int mdim=getMeshDimension();
5650 if(mdim<1 || mdim>3)
5651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5652 int nbCells=getNumberOfCells();
5653 const int *conn=_nodal_connec->getConstPointer();
5654 const int *connI=_nodal_connec_index->getConstPointer();
5655 for(int i=0;i<nbCells;i++)
5657 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5665 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5667 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5669 checkConnectivityFullyDefined();
5670 if(getMeshDimension()!=2)
5671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5672 int nbOfCells=getNumberOfCells();
5673 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5674 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5675 ret->alloc(nbOfCells+nbOfCutCells,1);
5676 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5677 int *retPt=ret->getPointer();
5678 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5680 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5681 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5682 int *pt=newConn->getPointer();
5683 int *ptI=newConnI->getPointer();
5685 const int *oldc=_nodal_connec->getConstPointer();
5686 const int *ci=_nodal_connec_index->getConstPointer();
5687 for(int i=0;i<nbOfCells;i++,ci++)
5689 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5691 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5692 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5693 pt=std::copy(tmp,tmp+8,pt);
5702 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5703 ptI[1]=ptI[0]+ci[1]-ci[0];
5708 _nodal_connec->decrRef();
5709 _nodal_connec=newConn.retn();
5710 _nodal_connec_index->decrRef();
5711 _nodal_connec_index=newConnI.retn();
5718 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5720 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5722 checkConnectivityFullyDefined();
5723 if(getMeshDimension()!=2)
5724 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5725 int nbOfCells=getNumberOfCells();
5726 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5727 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5728 ret->alloc(nbOfCells+nbOfCutCells,1);
5729 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5730 int *retPt=ret->getPointer();
5731 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5732 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5733 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5734 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5735 int *pt=newConn->getPointer();
5736 int *ptI=newConnI->getPointer();
5738 const int *oldc=_nodal_connec->getConstPointer();
5739 const int *ci=_nodal_connec_index->getConstPointer();
5740 for(int i=0;i<nbOfCells;i++,ci++)
5742 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5744 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5745 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5746 pt=std::copy(tmp,tmp+8,pt);
5755 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5756 ptI[1]=ptI[0]+ci[1]-ci[0];
5761 _nodal_connec->decrRef();
5762 _nodal_connec=newConn.retn();
5763 _nodal_connec_index->decrRef();
5764 _nodal_connec_index=newConnI.retn();
5771 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5773 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5775 checkConnectivityFullyDefined();
5776 if(getMeshDimension()!=3)
5777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5778 int nbOfCells=getNumberOfCells();
5779 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5780 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5781 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5782 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5783 int *retPt=ret->getPointer();
5784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5785 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5786 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5787 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5788 int *pt=newConn->getPointer();
5789 int *ptI=newConnI->getPointer();
5791 const int *oldc=_nodal_connec->getConstPointer();
5792 const int *ci=_nodal_connec_index->getConstPointer();
5793 for(int i=0;i<nbOfCells;i++,ci++)
5795 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5797 for(int j=0;j<5;j++,pt+=5,ptI++)
5799 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5800 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];
5807 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5808 ptI[1]=ptI[0]+ci[1]-ci[0];
5813 _nodal_connec->decrRef();
5814 _nodal_connec=newConn.retn();
5815 _nodal_connec_index->decrRef();
5816 _nodal_connec_index=newConnI.retn();
5823 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5825 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5827 checkConnectivityFullyDefined();
5828 if(getMeshDimension()!=3)
5829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5830 int nbOfCells=getNumberOfCells();
5831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5832 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5833 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5834 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5835 int *retPt=ret->getPointer();
5836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5838 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5839 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5840 int *pt=newConn->getPointer();
5841 int *ptI=newConnI->getPointer();
5843 const int *oldc=_nodal_connec->getConstPointer();
5844 const int *ci=_nodal_connec_index->getConstPointer();
5845 for(int i=0;i<nbOfCells;i++,ci++)
5847 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5849 for(int j=0;j<6;j++,pt+=5,ptI++)
5851 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5852 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];
5859 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5860 ptI[1]=ptI[0]+ci[1]-ci[0];
5865 _nodal_connec->decrRef();
5866 _nodal_connec=newConn.retn();
5867 _nodal_connec_index->decrRef();
5868 _nodal_connec_index=newConnI.retn();
5875 * 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.
5876 * This method completly ignore coordinates.
5877 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5878 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5879 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5880 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5882 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5884 checkFullyDefined();
5885 if(getMeshDimension()!=2)
5886 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5887 int nbOfCells=getNumberOfCells();
5888 int *connI=_nodal_connec_index->getPointer();
5890 for(int i=0;i<nbOfCells;i++,connI++)
5892 int offset=descIndex[i];
5893 int nbOfEdges=descIndex[i+1]-offset;
5895 bool ddirect=desc[offset+nbOfEdges-1]>0;
5896 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5897 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5898 for(int j=0;j<nbOfEdges;j++)
5900 bool direct=desc[offset+j]>0;
5901 int edgeId=std::abs(desc[offset+j])-1;
5902 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5904 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5905 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5906 int ref2=direct?id1:id2;
5909 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5910 newConnLgth+=nbOfSubNodes-1;
5915 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5916 throw INTERP_KERNEL::Exception(oss.str().c_str());
5921 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5924 newConnLgth++;//+1 is for cell type
5925 connI[1]=newConnLgth;
5928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5929 newConn->alloc(newConnLgth,1);
5930 int *work=newConn->getPointer();
5931 for(int i=0;i<nbOfCells;i++)
5933 *work++=INTERP_KERNEL::NORM_POLYGON;
5934 int offset=descIndex[i];
5935 int nbOfEdges=descIndex[i+1]-offset;
5936 for(int j=0;j<nbOfEdges;j++)
5938 bool direct=desc[offset+j]>0;
5939 int edgeId=std::abs(desc[offset+j])-1;
5941 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5944 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5945 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5946 work=std::copy(it,it+nbOfSubNodes-1,work);
5950 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5953 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5957 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5958 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5959 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5960 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5961 * so it can be useful to call mergeNodes() before calling this method.
5962 * \throw If \a this->getMeshDimension() <= 1.
5963 * \throw If the coordinates array is not set.
5964 * \throw If the nodal connectivity of cells is not defined.
5966 void MEDCouplingUMesh::convertDegeneratedCells()
5968 checkFullyDefined();
5969 if(getMeshDimension()<=1)
5970 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5971 int nbOfCells=getNumberOfCells();
5974 int initMeshLgth=getMeshLength();
5975 int *conn=_nodal_connec->getPointer();
5976 int *index=_nodal_connec_index->getPointer();
5980 for(int i=0;i<nbOfCells;i++)
5982 lgthOfCurCell=index[i+1]-posOfCurCell;
5983 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5985 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5986 conn+newPos+1,newLgth);
5987 conn[newPos]=newType;
5989 posOfCurCell=index[i+1];
5992 if(newPos!=initMeshLgth)
5993 _nodal_connec->reAlloc(newPos);
5998 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5999 * A cell is considered to be oriented correctly if an angle between its
6000 * normal vector and a given vector is less than \c PI / \c 2.
6001 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6003 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6005 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6006 * is not cleared before filling in.
6007 * \throw If \a this->getMeshDimension() != 2.
6008 * \throw If \a this->getSpaceDimension() != 3.
6010 * \if ENABLE_EXAMPLES
6011 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6012 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6015 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6017 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6018 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6019 int nbOfCells=getNumberOfCells();
6020 const int *conn=_nodal_connec->getConstPointer();
6021 const int *connI=_nodal_connec_index->getConstPointer();
6022 const double *coordsPtr=_coords->getConstPointer();
6023 for(int i=0;i<nbOfCells;i++)
6025 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6026 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6028 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6029 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6036 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6037 * considered to be oriented correctly if an angle between its normal vector and a
6038 * given vector is less than \c PI / \c 2.
6039 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6041 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6043 * \throw If \a this->getMeshDimension() != 2.
6044 * \throw If \a this->getSpaceDimension() != 3.
6046 * \if ENABLE_EXAMPLES
6047 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6048 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6051 * \sa changeOrientationOfCells
6053 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6055 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6056 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6057 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6058 const int *connI(_nodal_connec_index->getConstPointer());
6059 const double *coordsPtr(_coords->getConstPointer());
6060 bool isModified(false);
6061 for(int i=0;i<nbOfCells;i++)
6063 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6064 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6066 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6067 bool isQuadratic(cm.isQuadratic());
6068 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6071 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6076 _nodal_connec->declareAsNew();
6081 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6083 * \sa orientCorrectly2DCells
6085 void MEDCouplingUMesh::changeOrientationOfCells()
6087 int mdim(getMeshDimension());
6088 if(mdim!=2 && mdim!=1)
6089 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6090 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6091 const int *connI(_nodal_connec_index->getConstPointer());
6094 for(int i=0;i<nbOfCells;i++)
6096 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6097 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6098 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6103 for(int i=0;i<nbOfCells;i++)
6105 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6106 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6107 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6113 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6114 * oriented facets. The normal vector of the facet should point out of the cell.
6115 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6116 * is not cleared before filling in.
6117 * \throw If \a this->getMeshDimension() != 3.
6118 * \throw If \a this->getSpaceDimension() != 3.
6119 * \throw If the coordinates array is not set.
6120 * \throw If the nodal connectivity of cells is not defined.
6122 * \if ENABLE_EXAMPLES
6123 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6124 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6127 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6129 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6130 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6131 int nbOfCells=getNumberOfCells();
6132 const int *conn=_nodal_connec->getConstPointer();
6133 const int *connI=_nodal_connec_index->getConstPointer();
6134 const double *coordsPtr=_coords->getConstPointer();
6135 for(int i=0;i<nbOfCells;i++)
6137 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6138 if(type==INTERP_KERNEL::NORM_POLYHED)
6140 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6147 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6149 * \throw If \a this->getMeshDimension() != 3.
6150 * \throw If \a this->getSpaceDimension() != 3.
6151 * \throw If the coordinates array is not set.
6152 * \throw If the nodal connectivity of cells is not defined.
6153 * \throw If the reparation fails.
6155 * \if ENABLE_EXAMPLES
6156 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6157 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6159 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6161 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6163 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6164 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6165 int nbOfCells=getNumberOfCells();
6166 int *conn=_nodal_connec->getPointer();
6167 const int *connI=_nodal_connec_index->getConstPointer();
6168 const double *coordsPtr=_coords->getConstPointer();
6169 for(int i=0;i<nbOfCells;i++)
6171 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6172 if(type==INTERP_KERNEL::NORM_POLYHED)
6176 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6177 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6179 catch(INTERP_KERNEL::Exception& e)
6181 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6182 throw INTERP_KERNEL::Exception(oss.str().c_str());
6190 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6191 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6192 * according to which the first facet of the cell should be oriented to have the normal vector
6193 * pointing out of cell.
6194 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6195 * cells. The caller is to delete this array using decrRef() as it is no more
6197 * \throw If \a this->getMeshDimension() != 3.
6198 * \throw If \a this->getSpaceDimension() != 3.
6199 * \throw If the coordinates array is not set.
6200 * \throw If the nodal connectivity of cells is not defined.
6202 * \if ENABLE_EXAMPLES
6203 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6204 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6206 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6208 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6210 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6211 if(getMeshDimension()!=3)
6212 throw INTERP_KERNEL::Exception(msg);
6213 int spaceDim=getSpaceDimension();
6215 throw INTERP_KERNEL::Exception(msg);
6217 int nbOfCells=getNumberOfCells();
6218 int *conn=_nodal_connec->getPointer();
6219 const int *connI=_nodal_connec_index->getConstPointer();
6220 const double *coo=getCoords()->getConstPointer();
6221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6222 for(int i=0;i<nbOfCells;i++)
6224 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6225 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6227 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6229 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6230 cells->pushBackSilent(i);
6234 return cells.retn();
6238 * This method is a faster method to correct orientation of all 3D cells in \a this.
6239 * 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.
6240 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6242 * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6243 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6245 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6247 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6248 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6249 int nbOfCells=getNumberOfCells();
6250 int *conn=_nodal_connec->getPointer();
6251 const int *connI=_nodal_connec_index->getConstPointer();
6252 const double *coordsPtr=_coords->getConstPointer();
6253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6254 for(int i=0;i<nbOfCells;i++)
6256 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6259 case INTERP_KERNEL::NORM_TETRA4:
6261 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6263 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6264 ret->pushBackSilent(i);
6268 case INTERP_KERNEL::NORM_PYRA5:
6270 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6272 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6273 ret->pushBackSilent(i);
6277 case INTERP_KERNEL::NORM_PENTA6:
6278 case INTERP_KERNEL::NORM_HEXA8:
6279 case INTERP_KERNEL::NORM_HEXGP12:
6281 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6283 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6284 ret->pushBackSilent(i);
6288 case INTERP_KERNEL::NORM_POLYHED:
6290 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6292 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6293 ret->pushBackSilent(i);
6298 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 !");
6306 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6307 * If it is not the case an exception will be thrown.
6308 * This method is fast because the first cell of \a this is used to compute the plane.
6309 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6310 * \param pos output of size at least 3 used to store a point owned of searched plane.
6312 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6314 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6315 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6316 const int *conn=_nodal_connec->getConstPointer();
6317 const int *connI=_nodal_connec_index->getConstPointer();
6318 const double *coordsPtr=_coords->getConstPointer();
6319 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6320 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6324 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6325 * cells. Currently cells of the following types are treated:
6326 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6327 * For a cell of other type an exception is thrown.
6328 * Space dimension of a 2D mesh can be either 2 or 3.
6329 * The Edge Ratio of a cell \f$t\f$ is:
6330 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6331 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6332 * the smallest edge lengths of \f$t\f$.
6333 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6334 * cells and one time, lying on \a this mesh. The caller is to delete this
6335 * field using decrRef() as it is no more needed.
6336 * \throw If the coordinates array is not set.
6337 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6338 * \throw If the connectivity data array has more than one component.
6339 * \throw If the connectivity data array has a named component.
6340 * \throw If the connectivity index data array has more than one component.
6341 * \throw If the connectivity index data array has a named component.
6342 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6343 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6344 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6346 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6349 int spaceDim=getSpaceDimension();
6350 int meshDim=getMeshDimension();
6351 if(spaceDim!=2 && spaceDim!=3)
6352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6353 if(meshDim!=2 && meshDim!=3)
6354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6355 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6357 int nbOfCells=getNumberOfCells();
6358 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6359 arr->alloc(nbOfCells,1);
6360 double *pt=arr->getPointer();
6361 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6362 const int *conn=_nodal_connec->getConstPointer();
6363 const int *connI=_nodal_connec_index->getConstPointer();
6364 const double *coo=_coords->getConstPointer();
6366 for(int i=0;i<nbOfCells;i++,pt++)
6368 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6371 case INTERP_KERNEL::NORM_TRI3:
6373 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6374 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6377 case INTERP_KERNEL::NORM_QUAD4:
6379 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6380 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6383 case INTERP_KERNEL::NORM_TETRA4:
6385 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6386 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6392 conn+=connI[i+1]-connI[i];
6394 ret->setName("EdgeRatio");
6395 ret->synchronizeTimeWithSupport();
6400 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6401 * cells. Currently cells of the following types are treated:
6402 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6403 * For a cell of other type an exception is thrown.
6404 * Space dimension of a 2D mesh can be either 2 or 3.
6405 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6406 * cells and one time, lying on \a this mesh. The caller is to delete this
6407 * field using decrRef() as it is no more needed.
6408 * \throw If the coordinates array is not set.
6409 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6410 * \throw If the connectivity data array has more than one component.
6411 * \throw If the connectivity data array has a named component.
6412 * \throw If the connectivity index data array has more than one component.
6413 * \throw If the connectivity index data array has a named component.
6414 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6415 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6416 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6418 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6421 int spaceDim=getSpaceDimension();
6422 int meshDim=getMeshDimension();
6423 if(spaceDim!=2 && spaceDim!=3)
6424 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6425 if(meshDim!=2 && meshDim!=3)
6426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6427 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6429 int nbOfCells=getNumberOfCells();
6430 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6431 arr->alloc(nbOfCells,1);
6432 double *pt=arr->getPointer();
6433 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6434 const int *conn=_nodal_connec->getConstPointer();
6435 const int *connI=_nodal_connec_index->getConstPointer();
6436 const double *coo=_coords->getConstPointer();
6438 for(int i=0;i<nbOfCells;i++,pt++)
6440 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6443 case INTERP_KERNEL::NORM_TRI3:
6445 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6446 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6449 case INTERP_KERNEL::NORM_QUAD4:
6451 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6452 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6455 case INTERP_KERNEL::NORM_TETRA4:
6457 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6458 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6464 conn+=connI[i+1]-connI[i];
6466 ret->setName("AspectRatio");
6467 ret->synchronizeTimeWithSupport();
6472 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6473 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6474 * treated: INTERP_KERNEL::NORM_QUAD4.
6475 * For a cell of other type an exception is thrown.
6476 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6477 * cells and one time, lying on \a this mesh. The caller is to delete this
6478 * field using decrRef() as it is no more needed.
6479 * \throw If the coordinates array is not set.
6480 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6481 * \throw If the connectivity data array has more than one component.
6482 * \throw If the connectivity data array has a named component.
6483 * \throw If the connectivity index data array has more than one component.
6484 * \throw If the connectivity index data array has a named component.
6485 * \throw If \a this->getMeshDimension() != 2.
6486 * \throw If \a this->getSpaceDimension() != 3.
6487 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6489 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6492 int spaceDim=getSpaceDimension();
6493 int meshDim=getMeshDimension();
6495 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6497 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6498 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6500 int nbOfCells=getNumberOfCells();
6501 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6502 arr->alloc(nbOfCells,1);
6503 double *pt=arr->getPointer();
6504 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6505 const int *conn=_nodal_connec->getConstPointer();
6506 const int *connI=_nodal_connec_index->getConstPointer();
6507 const double *coo=_coords->getConstPointer();
6509 for(int i=0;i<nbOfCells;i++,pt++)
6511 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6514 case INTERP_KERNEL::NORM_QUAD4:
6516 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6517 *pt=INTERP_KERNEL::quadWarp(tmp);
6521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6523 conn+=connI[i+1]-connI[i];
6525 ret->setName("Warp");
6526 ret->synchronizeTimeWithSupport();
6532 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6533 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6534 * treated: INTERP_KERNEL::NORM_QUAD4.
6535 * For a cell of other type an exception is thrown.
6536 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6537 * cells and one time, lying on \a this mesh. The caller is to delete this
6538 * field using decrRef() as it is no more needed.
6539 * \throw If the coordinates array is not set.
6540 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6541 * \throw If the connectivity data array has more than one component.
6542 * \throw If the connectivity data array has a named component.
6543 * \throw If the connectivity index data array has more than one component.
6544 * \throw If the connectivity index data array has a named component.
6545 * \throw If \a this->getMeshDimension() != 2.
6546 * \throw If \a this->getSpaceDimension() != 3.
6547 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6549 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6552 int spaceDim=getSpaceDimension();
6553 int meshDim=getMeshDimension();
6555 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6557 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6558 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6560 int nbOfCells=getNumberOfCells();
6561 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6562 arr->alloc(nbOfCells,1);
6563 double *pt=arr->getPointer();
6564 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6565 const int *conn=_nodal_connec->getConstPointer();
6566 const int *connI=_nodal_connec_index->getConstPointer();
6567 const double *coo=_coords->getConstPointer();
6569 for(int i=0;i<nbOfCells;i++,pt++)
6571 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6574 case INTERP_KERNEL::NORM_QUAD4:
6576 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6577 *pt=INTERP_KERNEL::quadSkew(tmp);
6581 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6583 conn+=connI[i+1]-connI[i];
6585 ret->setName("Skew");
6586 ret->synchronizeTimeWithSupport();
6591 * 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.
6593 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6595 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6597 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6600 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6602 std::set<INTERP_KERNEL::NormalizedCellType> types;
6603 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6604 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6605 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6606 arr->alloc(nbCells,1);
6607 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6609 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6611 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6614 ret->setName("Diameter");
6619 * This method aggregate the bbox of each cell and put it into bbox parameter.
6621 * \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)
6622 * For all other cases this input parameter is ignored.
6623 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6625 * \throw If \a this is not fully set (coordinates and connectivity).
6626 * \throw If a cell in \a this has no valid nodeId.
6627 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6629 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6631 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6632 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.
6633 return getBoundingBoxForBBTreeFast();
6634 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6636 bool presenceOfQuadratic(false);
6637 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6639 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6640 if(cm.isQuadratic())
6641 presenceOfQuadratic=true;
6643 if(!presenceOfQuadratic)
6644 return getBoundingBoxForBBTreeFast();
6645 if(mDim==2 && sDim==2)
6646 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6648 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6650 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) !");
6654 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6655 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6657 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6659 * \throw If \a this is not fully set (coordinates and connectivity).
6660 * \throw If a cell in \a this has no valid nodeId.
6662 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6664 checkFullyDefined();
6665 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6666 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6667 double *bbox(ret->getPointer());
6668 for(int i=0;i<nbOfCells*spaceDim;i++)
6670 bbox[2*i]=std::numeric_limits<double>::max();
6671 bbox[2*i+1]=-std::numeric_limits<double>::max();
6673 const double *coordsPtr(_coords->getConstPointer());
6674 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6675 for(int i=0;i<nbOfCells;i++)
6677 int offset=connI[i]+1;
6678 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6679 for(int j=0;j<nbOfNodesForCell;j++)
6681 int nodeId=conn[offset+j];
6682 if(nodeId>=0 && nodeId<nbOfNodes)
6684 for(int k=0;k<spaceDim;k++)
6686 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6687 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6694 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6695 throw INTERP_KERNEL::Exception(oss.str().c_str());
6702 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6703 * useful for 2D meshes having quadratic cells
6704 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6705 * the two extremities of the arc of circle).
6707 * \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)
6708 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6709 * \throw If \a this is not fully defined.
6710 * \throw If \a this is not a mesh with meshDimension equal to 2.
6711 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6712 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6714 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6716 checkFullyDefined();
6717 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6718 if(spaceDim!=2 || mDim!=2)
6719 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!");
6720 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6721 double *bbox(ret->getPointer());
6722 const double *coords(_coords->getConstPointer());
6723 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6724 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6726 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6727 int sz(connI[1]-connI[0]-1);
6728 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6729 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6730 INTERP_KERNEL::QuadraticPolygon *pol(0);
6731 for(int j=0;j<sz;j++)
6733 int nodeId(conn[*connI+1+j]);
6734 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6736 if(!cm.isQuadratic())
6737 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6739 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6740 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6741 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6747 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6748 * useful for 2D meshes having quadratic cells
6749 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6750 * the two extremities of the arc of circle).
6752 * \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)
6753 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6754 * \throw If \a this is not fully defined.
6755 * \throw If \a this is not a mesh with meshDimension equal to 1.
6756 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6757 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6759 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6761 checkFullyDefined();
6762 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6763 if(spaceDim!=2 || mDim!=1)
6764 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!");
6765 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6766 double *bbox(ret->getPointer());
6767 const double *coords(_coords->getConstPointer());
6768 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6769 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6771 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6772 int sz(connI[1]-connI[0]-1);
6773 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6774 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6775 INTERP_KERNEL::Edge *edge(0);
6776 for(int j=0;j<sz;j++)
6778 int nodeId(conn[*connI+1+j]);
6779 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6781 if(!cm.isQuadratic())
6782 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6784 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6785 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6786 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6793 namespace ParaMEDMEMImpl
6798 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6799 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6808 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6809 bool operator() (const int& pos) { return _conn[pos]==_val; }
6819 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6820 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6821 * \a this is composed in cell types.
6822 * The returned array is of size 3*n where n is the number of different types present in \a this.
6823 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6824 * This parameter is kept only for compatibility with other methode listed above.
6826 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6828 checkConnectivityFullyDefined();
6829 const int *conn=_nodal_connec->getConstPointer();
6830 const int *connI=_nodal_connec_index->getConstPointer();
6831 const int *work=connI;
6832 int nbOfCells=getNumberOfCells();
6833 std::size_t n=getAllGeoTypes().size();
6834 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6835 std::set<INTERP_KERNEL::NormalizedCellType> types;
6836 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6838 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6839 if(types.find(typ)!=types.end())
6841 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6842 oss << " is not contiguous !";
6843 throw INTERP_KERNEL::Exception(oss.str().c_str());
6847 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6848 ret[3*i+1]=(int)std::distance(work,work2);
6855 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6856 * only for types cell, type node is not managed.
6857 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6858 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6859 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6860 * If 2 or more same geometric type is in \a code and exception is thrown too.
6862 * This method firstly checks
6863 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6864 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6865 * an exception is thrown too.
6867 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6868 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6869 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6871 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6875 std::size_t sz=code.size();
6878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6879 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6881 bool isNoPflUsed=true;
6882 for(std::size_t i=0;i<n;i++)
6883 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6885 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6887 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6889 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6892 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6895 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6896 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6897 if(types.size()==_types.size())
6900 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6902 int *retPtr=ret->getPointer();
6903 const int *connI=_nodal_connec_index->getConstPointer();
6904 const int *conn=_nodal_connec->getConstPointer();
6905 int nbOfCells=getNumberOfCells();
6908 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6910 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6911 int offset=(int)std::distance(connI,i);
6912 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6913 int nbOfCellsOfCurType=(int)std::distance(i,j);
6914 if(code[3*kk+2]==-1)
6915 for(int k=0;k<nbOfCellsOfCurType;k++)
6919 int idInIdsPerType=code[3*kk+2];
6920 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6922 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6925 zePfl->checkAllocated();
6926 if(zePfl->getNumberOfComponents()==1)
6928 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6930 if(*k>=0 && *k<nbOfCellsOfCurType)
6931 *retPtr=(*k)+offset;
6934 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6935 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6936 throw INTERP_KERNEL::Exception(oss.str().c_str());
6941 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6944 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6948 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6949 oss << " should be in [0," << idsPerType.size() << ") !";
6950 throw INTERP_KERNEL::Exception(oss.str().c_str());
6959 * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6960 * 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.
6961 * 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.
6962 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6964 * \param [in] profile
6965 * \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.
6966 * \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,
6967 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6968 * \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.
6969 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6970 * \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
6972 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6975 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6976 if(profile->getNumberOfComponents()!=1)
6977 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6978 checkConnectivityFullyDefined();
6979 const int *conn=_nodal_connec->getConstPointer();
6980 const int *connI=_nodal_connec_index->getConstPointer();
6981 int nbOfCells=getNumberOfCells();
6982 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6983 std::vector<int> typeRangeVals(1);
6984 for(const int *i=connI;i!=connI+nbOfCells;)
6986 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6987 if(std::find(types.begin(),types.end(),curType)!=types.end())
6989 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6991 types.push_back(curType);
6992 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6993 typeRangeVals.push_back((int)std::distance(connI,i));
6996 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6997 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6998 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
7000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
7002 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7003 code.resize(3*nbOfCastsFinal);
7004 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7005 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7006 for(int i=0;i<nbOfCastsFinal;i++)
7008 int castId=castsPresent->getIJ(i,0);
7009 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7010 idsInPflPerType2.push_back(tmp3);
7011 code[3*i]=(int)types[castId];
7012 code[3*i+1]=tmp3->getNumberOfTuples();
7013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7014 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
7016 tmp4->copyStringInfoFrom(*profile);
7017 idsPerType2.push_back(tmp4);
7018 code[3*i+2]=(int)idsPerType2.size()-1;
7025 std::size_t sz2=idsInPflPerType2.size();
7026 idsInPflPerType.resize(sz2);
7027 for(std::size_t i=0;i<sz2;i++)
7029 DataArrayInt *locDa=idsInPflPerType2[i];
7031 idsInPflPerType[i]=locDa;
7033 std::size_t sz=idsPerType2.size();
7034 idsPerType.resize(sz);
7035 for(std::size_t i=0;i<sz;i++)
7037 DataArrayInt *locDa=idsPerType2[i];
7039 idsPerType[i]=locDa;
7044 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7045 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7046 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7047 * 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.
7049 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7051 checkFullyDefined();
7052 nM1LevMesh->checkFullyDefined();
7053 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7054 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7055 if(_coords!=nM1LevMesh->getCoords())
7056 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7059 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7061 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7062 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7063 tmp->setConnectivity(tmp0,tmp1);
7064 tmp->renumberCells(ret0->getConstPointer(),false);
7065 revDesc=tmp->getNodalConnectivity();
7066 revDescIndx=tmp->getNodalConnectivityIndex();
7067 DataArrayInt *ret=0;
7068 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7071 ret->getMaxValue(tmp2);
7073 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7074 throw INTERP_KERNEL::Exception(oss.str().c_str());
7079 revDescIndx->incrRef();
7082 meshnM1Old2New=ret0;
7087 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7088 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7089 * in "Old to New" mode.
7090 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7091 * this array using decrRef() as it is no more needed.
7092 * \throw If the nodal connectivity of cells is not defined.
7094 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7096 checkConnectivityFullyDefined();
7097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7098 renumberCells(ret->getConstPointer(),false);
7103 * This methods checks that cells are sorted by their types.
7104 * This method makes asumption (no check) that connectivity is correctly set before calling.
7106 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7108 checkFullyDefined();
7109 const int *conn=_nodal_connec->getConstPointer();
7110 const int *connI=_nodal_connec_index->getConstPointer();
7111 int nbOfCells=getNumberOfCells();
7112 std::set<INTERP_KERNEL::NormalizedCellType> types;
7113 for(const int *i=connI;i!=connI+nbOfCells;)
7115 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7116 if(types.find(curType)!=types.end())
7118 types.insert(curType);
7119 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7125 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7126 * The geometric type order is specified by MED file.
7128 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7130 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7132 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7136 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7137 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7138 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7139 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7141 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7143 checkFullyDefined();
7144 const int *conn=_nodal_connec->getConstPointer();
7145 const int *connI=_nodal_connec_index->getConstPointer();
7146 int nbOfCells=getNumberOfCells();
7150 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7151 for(const int *i=connI;i!=connI+nbOfCells;)
7153 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7154 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7155 if(isTypeExists!=orderEnd)
7157 int pos=(int)std::distance(orderBg,isTypeExists);
7161 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7165 if(sg.find(curType)==sg.end())
7167 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7178 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7179 * 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
7180 * 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'.
7182 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7184 checkConnectivityFullyDefined();
7185 int nbOfCells=getNumberOfCells();
7186 const int *conn=_nodal_connec->getConstPointer();
7187 const int *connI=_nodal_connec_index->getConstPointer();
7188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7190 tmpa->alloc(nbOfCells,1);
7191 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7192 tmpb->fillWithZero();
7193 int *tmp=tmpa->getPointer();
7194 int *tmp2=tmpb->getPointer();
7195 for(const int *i=connI;i!=connI+nbOfCells;i++)
7197 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7200 int pos=(int)std::distance(orderBg,where);
7202 tmp[std::distance(connI,i)]=pos;
7206 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7207 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7208 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7209 throw INTERP_KERNEL::Exception(oss.str().c_str());
7212 nbPerType=tmpb.retn();
7217 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7219 * \return a new object containing the old to new correspondance.
7221 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7223 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7225 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7229 * 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.
7230 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7231 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7232 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7234 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7236 DataArrayInt *nbPerType=0;
7237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7238 nbPerType->decrRef();
7239 return tmpa->buildPermArrPerLevel();
7243 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7244 * The number of cells remains unchanged after the call of this method.
7245 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7246 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7248 * \return the array giving the correspondance old to new.
7250 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7252 checkFullyDefined();
7254 const int *conn=_nodal_connec->getConstPointer();
7255 const int *connI=_nodal_connec_index->getConstPointer();
7256 int nbOfCells=getNumberOfCells();
7257 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7258 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7259 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7261 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7262 types.push_back(curType);
7263 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7265 DataArrayInt *ret=DataArrayInt::New();
7266 ret->alloc(nbOfCells,1);
7267 int *retPtr=ret->getPointer();
7268 std::fill(retPtr,retPtr+nbOfCells,-1);
7270 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7272 for(const int *i=connI;i!=connI+nbOfCells;i++)
7273 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7274 retPtr[std::distance(connI,i)]=newCellId++;
7276 renumberCells(retPtr,false);
7281 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7282 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7283 * This method makes asumption that connectivity is correctly set before calling.
7285 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7287 checkConnectivityFullyDefined();
7288 const int *conn=_nodal_connec->getConstPointer();
7289 const int *connI=_nodal_connec_index->getConstPointer();
7290 int nbOfCells=getNumberOfCells();
7291 std::vector<MEDCouplingUMesh *> ret;
7292 for(const int *i=connI;i!=connI+nbOfCells;)
7294 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7295 int beginCellId=(int)std::distance(connI,i);
7296 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7297 int endCellId=(int)std::distance(connI,i);
7298 int sz=endCellId-beginCellId;
7299 int *cells=new int[sz];
7300 for(int j=0;j<sz;j++)
7301 cells[j]=beginCellId+j;
7302 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7310 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7311 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7312 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7314 * \return a newly allocated instance, that the caller must manage.
7315 * \throw If \a this contains more than one geometric type.
7316 * \throw If the nodal connectivity of \a this is not fully defined.
7317 * \throw If the internal data is not coherent.
7319 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7321 checkConnectivityFullyDefined();
7322 if(_types.size()!=1)
7323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7324 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7325 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7326 ret->setCoords(getCoords());
7327 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7331 retC->setNodalConnectivity(c);
7335 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7337 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7338 DataArrayInt *c=0,*ci=0;
7339 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7340 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7341 retD->setNodalConnectivity(cs,cis);
7346 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7348 checkConnectivityFullyDefined();
7349 if(_types.size()!=1)
7350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7351 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7352 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7355 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7356 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7357 throw INTERP_KERNEL::Exception(oss.str().c_str());
7359 int nbCells=getNumberOfCells();
7361 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7363 int *outPtr=connOut->getPointer();
7364 const int *conn=_nodal_connec->begin();
7365 const int *connI=_nodal_connec_index->begin();
7367 for(int i=0;i<nbCells;i++,connI++)
7369 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7370 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7373 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 << ") !";
7374 throw INTERP_KERNEL::Exception(oss.str().c_str());
7377 return connOut.retn();
7381 * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7382 * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7386 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7388 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7389 checkConnectivityFullyDefined();
7390 if(_types.size()!=1)
7391 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7392 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7394 throw INTERP_KERNEL::Exception(msg0);
7395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7396 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7397 int *cp(c->getPointer()),*cip(ci->getPointer());
7398 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7400 for(int i=0;i<nbCells;i++,cip++,incip++)
7402 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7403 int delta(stop-strt);
7406 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7407 cp=std::copy(incp+strt,incp+stop,cp);
7409 throw INTERP_KERNEL::Exception(msg0);
7412 throw INTERP_KERNEL::Exception(msg0);
7413 cip[1]=cip[0]+delta;
7415 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7419 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7420 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7421 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7422 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7423 * are not used here to avoid the build of big permutation array.
7425 * \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
7426 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7427 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7428 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7429 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7430 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7431 * \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
7432 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7434 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7435 DataArrayInt *&szOfCellGrpOfSameType,
7436 DataArrayInt *&idInMsOfCellGrpOfSameType)
7438 std::vector<const MEDCouplingUMesh *> ms2;
7439 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7442 (*it)->checkConnectivityFullyDefined();
7446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7447 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7448 int meshDim=ms2[0]->getMeshDimension();
7449 std::vector<const MEDCouplingUMesh *> m1ssm;
7450 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7452 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7453 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7456 ret1->alloc(0,1); ret2->alloc(0,1);
7457 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7459 if(meshDim!=(*it)->getMeshDimension())
7460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7461 if(refCoo!=(*it)->getCoords())
7462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7463 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7464 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7465 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7466 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7468 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7469 m1ssmSingleAuto.push_back(singleCell);
7470 m1ssmSingle.push_back(singleCell);
7471 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7474 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7475 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7476 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7477 for(std::size_t i=0;i<m1ssm.size();i++)
7478 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7479 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7480 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7481 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7486 * This method returns a newly created DataArrayInt instance.
7487 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7489 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7491 checkFullyDefined();
7492 const int *conn=_nodal_connec->getConstPointer();
7493 const int *connIndex=_nodal_connec_index->getConstPointer();
7494 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7495 for(const int *w=begin;w!=end;w++)
7496 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7497 ret->pushBackSilent(*w);
7502 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7503 * are in [0:getNumberOfCells())
7505 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7507 checkFullyDefined();
7508 const int *conn=_nodal_connec->getConstPointer();
7509 const int *connI=_nodal_connec_index->getConstPointer();
7510 int nbOfCells=getNumberOfCells();
7511 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7512 int *tmp=new int[nbOfCells];
7513 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7516 for(const int *i=connI;i!=connI+nbOfCells;i++)
7517 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7518 tmp[std::distance(connI,i)]=j++;
7520 DataArrayInt *ret=DataArrayInt::New();
7521 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7522 ret->copyStringInfoFrom(*da);
7523 int *retPtr=ret->getPointer();
7524 const int *daPtr=da->getConstPointer();
7525 int nbOfElems=da->getNbOfElems();
7526 for(int k=0;k<nbOfElems;k++)
7527 retPtr[k]=tmp[daPtr[k]];
7533 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7534 * This method \b works \b for mesh sorted by type.
7535 * cells whose ids is in 'idsPerGeoType' array.
7536 * This method conserves coords and name of mesh.
7538 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7540 std::vector<int> code=getDistributionOfTypes();
7541 std::size_t nOfTypesInThis=code.size()/3;
7542 int sz=0,szOfType=0;
7543 for(std::size_t i=0;i<nOfTypesInThis;i++)
7548 szOfType=code[3*i+1];
7550 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7551 if(*work<0 || *work>=szOfType)
7553 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7554 oss << ". It should be in [0," << szOfType << ") !";
7555 throw INTERP_KERNEL::Exception(oss.str().c_str());
7557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7558 int *idsPtr=idsTokeep->getPointer();
7560 for(std::size_t i=0;i<nOfTypesInThis;i++)
7563 for(int j=0;j<code[3*i+1];j++)
7566 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7567 offset+=code[3*i+1];
7569 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7570 ret->copyTinyInfoFrom(this);
7575 * This method returns a vector of size 'this->getNumberOfCells()'.
7576 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7578 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7580 int ncell=getNumberOfCells();
7581 std::vector<bool> ret(ncell);
7582 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7583 const int *c=getNodalConnectivity()->getConstPointer();
7584 for(int i=0;i<ncell;i++)
7586 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7587 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7588 ret[i]=cm.isQuadratic();
7594 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7596 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7598 if(other->getType()!=UNSTRUCTURED)
7599 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7600 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7601 return MergeUMeshes(this,otherC);
7605 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7606 * computed by averaging coordinates of cell nodes, so this method is not a right
7607 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7608 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7609 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7610 * components. The caller is to delete this array using decrRef() as it is
7612 * \throw If the coordinates array is not set.
7613 * \throw If the nodal connectivity of cells is not defined.
7614 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7616 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7618 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7619 int spaceDim=getSpaceDimension();
7620 int nbOfCells=getNumberOfCells();
7621 ret->alloc(nbOfCells,spaceDim);
7622 ret->copyStringInfoFrom(*getCoords());
7623 double *ptToFill=ret->getPointer();
7624 const int *nodal=_nodal_connec->getConstPointer();
7625 const int *nodalI=_nodal_connec_index->getConstPointer();
7626 const double *coor=_coords->getConstPointer();
7627 for(int i=0;i<nbOfCells;i++)
7629 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7630 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7637 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7638 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7640 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7641 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7643 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7644 * \throw If \a this is not fully defined (coordinates and connectivity)
7645 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7647 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7649 checkFullyDefined();
7650 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7651 int spaceDim=getSpaceDimension();
7652 int nbOfCells=getNumberOfCells();
7653 int nbOfNodes=getNumberOfNodes();
7654 ret->alloc(nbOfCells,spaceDim);
7655 double *ptToFill=ret->getPointer();
7656 const int *nodal=_nodal_connec->getConstPointer();
7657 const int *nodalI=_nodal_connec_index->getConstPointer();
7658 const double *coor=_coords->getConstPointer();
7659 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7661 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7662 std::fill(ptToFill,ptToFill+spaceDim,0.);
7663 if(type!=INTERP_KERNEL::NORM_POLYHED)
7665 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7667 if(*conn>=0 && *conn<nbOfNodes)
7668 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7671 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7672 throw INTERP_KERNEL::Exception(oss.str().c_str());
7675 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7676 if(nbOfNodesInCell>0)
7677 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7680 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7681 throw INTERP_KERNEL::Exception(oss.str().c_str());
7686 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7688 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7690 if(*it>=0 && *it<nbOfNodes)
7691 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7694 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7695 throw INTERP_KERNEL::Exception(oss.str().c_str());
7699 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7702 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7703 throw INTERP_KERNEL::Exception(oss.str().c_str());
7711 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7712 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7713 * are specified via an array of cell ids.
7714 * \warning Validity of the specified cell ids is not checked!
7715 * Valid range is [ 0, \a this->getNumberOfCells() ).
7716 * \param [in] begin - an array of cell ids of interest.
7717 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7718 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7719 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7720 * caller is to delete this array using decrRef() as it is no more needed.
7721 * \throw If the coordinates array is not set.
7722 * \throw If the nodal connectivity of cells is not defined.
7724 * \if ENABLE_EXAMPLES
7725 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7726 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7729 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7731 DataArrayDouble *ret=DataArrayDouble::New();
7732 int spaceDim=getSpaceDimension();
7733 int nbOfTuple=(int)std::distance(begin,end);
7734 ret->alloc(nbOfTuple,spaceDim);
7735 double *ptToFill=ret->getPointer();
7736 double *tmp=new double[spaceDim];
7737 const int *nodal=_nodal_connec->getConstPointer();
7738 const int *nodalI=_nodal_connec_index->getConstPointer();
7739 const double *coor=_coords->getConstPointer();
7740 for(const int *w=begin;w!=end;w++)
7742 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7743 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7751 * 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".
7752 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7753 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7754 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7755 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7757 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7758 * \throw If spaceDim!=3 or meshDim!=2.
7759 * \throw If connectivity of \a this is invalid.
7760 * \throw If connectivity of a cell in \a this points to an invalid node.
7762 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7764 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7765 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7766 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7767 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7768 ret->alloc(nbOfCells,4);
7769 double *retPtr(ret->getPointer());
7770 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7771 const double *coor(_coords->begin());
7772 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7774 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7775 if(nodalI[1]-nodalI[0]>=3)
7777 for(int j=0;j<3;j++)
7779 int nodeId(nodal[nodalI[0]+1+j]);
7780 if(nodeId>=0 && nodeId<nbOfNodes)
7781 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7784 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7785 throw INTERP_KERNEL::Exception(oss.str().c_str());
7791 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7792 throw INTERP_KERNEL::Exception(oss.str().c_str());
7794 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7795 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7801 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7804 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7807 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7808 da->checkAllocated();
7809 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7811 int nbOfTuples=da->getNumberOfTuples();
7812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7814 c->alloc(2*nbOfTuples,1);
7815 cI->alloc(nbOfTuples+1,1);
7816 int *cp=c->getPointer();
7817 int *cip=cI->getPointer();
7819 for(int i=0;i<nbOfTuples;i++)
7821 *cp++=INTERP_KERNEL::NORM_POINT1;
7825 ret->setConnectivity(c,cI,true);
7829 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7830 * Cells and nodes of
7831 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7832 * \param [in] mesh1 - the first mesh.
7833 * \param [in] mesh2 - the second mesh.
7834 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7835 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7836 * is no more needed.
7837 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7838 * \throw If the coordinates array is not set in none of the meshes.
7839 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7840 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7842 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7844 std::vector<const MEDCouplingUMesh *> tmp(2);
7845 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7846 return MergeUMeshes(tmp);
7850 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7851 * Cells and nodes of
7852 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7853 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7854 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7855 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7856 * is no more needed.
7857 * \throw If \a a.size() == 0.
7858 * \throw If \a a[ *i* ] == NULL.
7859 * \throw If the coordinates array is not set in none of the meshes.
7860 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7861 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7863 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7865 std::size_t sz=a.size();
7867 return MergeUMeshesLL(a);
7868 for(std::size_t ii=0;ii<sz;ii++)
7871 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7872 throw INTERP_KERNEL::Exception(oss.str().c_str());
7874 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7875 std::vector< const MEDCouplingUMesh * > aa(sz);
7877 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7879 const MEDCouplingUMesh *cur=a[i];
7880 const DataArrayDouble *coo=cur->getCoords();
7882 spaceDim=coo->getNumberOfComponents();
7885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7886 for(std::size_t i=0;i<sz;i++)
7888 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7891 return MergeUMeshesLL(aa);
7896 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7899 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7900 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7901 int meshDim=(*it)->getMeshDimension();
7902 int nbOfCells=(*it)->getNumberOfCells();
7903 int meshLgth=(*it++)->getMeshLength();
7904 for(;it!=a.end();it++)
7906 if(meshDim!=(*it)->getMeshDimension())
7907 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7908 nbOfCells+=(*it)->getNumberOfCells();
7909 meshLgth+=(*it)->getMeshLength();
7911 std::vector<const MEDCouplingPointSet *> aps(a.size());
7912 std::copy(a.begin(),a.end(),aps.begin());
7913 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7914 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7915 ret->setCoords(pts);
7916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7917 c->alloc(meshLgth,1);
7918 int *cPtr=c->getPointer();
7919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7920 cI->alloc(nbOfCells+1,1);
7921 int *cIPtr=cI->getPointer();
7925 for(it=a.begin();it!=a.end();it++)
7927 int curNbOfCell=(*it)->getNumberOfCells();
7928 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7929 const int *curC=(*it)->_nodal_connec->getConstPointer();
7930 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7931 for(int j=0;j<curNbOfCell;j++)
7933 const int *src=curC+curCI[j];
7935 for(;src!=curC+curCI[j+1];src++,cPtr++)
7943 offset+=curCI[curNbOfCell];
7944 offset2+=(*it)->getNumberOfNodes();
7947 ret->setConnectivity(c,cI,true);
7954 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7955 * dimension and sharing the node coordinates array.
7956 * All cells of the first mesh precede all cells of the second mesh
7957 * within the result mesh.
7958 * \param [in] mesh1 - the first mesh.
7959 * \param [in] mesh2 - the second mesh.
7960 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7961 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7962 * is no more needed.
7963 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7964 * \throw If the meshes do not share the node coordinates array.
7965 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7966 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7968 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7970 std::vector<const MEDCouplingUMesh *> tmp(2);
7971 tmp[0]=mesh1; tmp[1]=mesh2;
7972 return MergeUMeshesOnSameCoords(tmp);
7976 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7977 * dimension and sharing the node coordinates array.
7978 * All cells of the *i*-th mesh precede all cells of the
7979 * (*i*+1)-th mesh within the result mesh.
7980 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7981 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7982 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7983 * is no more needed.
7984 * \throw If \a a.size() == 0.
7985 * \throw If \a a[ *i* ] == NULL.
7986 * \throw If the meshes do not share the node coordinates array.
7987 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7988 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7990 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7993 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7994 for(std::size_t ii=0;ii<meshes.size();ii++)
7997 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7998 throw INTERP_KERNEL::Exception(oss.str().c_str());
8000 const DataArrayDouble *coords=meshes.front()->getCoords();
8001 int meshDim=meshes.front()->getMeshDimension();
8002 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8004 int meshIndexLgth=0;
8005 for(;iter!=meshes.end();iter++)
8007 if(coords!=(*iter)->getCoords())
8008 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8009 if(meshDim!=(*iter)->getMeshDimension())
8010 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8011 meshLgth+=(*iter)->getMeshLength();
8012 meshIndexLgth+=(*iter)->getNumberOfCells();
8014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8015 nodal->alloc(meshLgth,1);
8016 int *nodalPtr=nodal->getPointer();
8017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8018 nodalIndex->alloc(meshIndexLgth+1,1);
8019 int *nodalIndexPtr=nodalIndex->getPointer();
8021 for(iter=meshes.begin();iter!=meshes.end();iter++)
8023 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8024 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8025 int nbOfCells=(*iter)->getNumberOfCells();
8026 int meshLgth2=(*iter)->getMeshLength();
8027 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8028 if(iter!=meshes.begin())
8029 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8031 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8034 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8035 ret->setName("merge");
8036 ret->setMeshDimension(meshDim);
8037 ret->setConnectivity(nodal,nodalIndex,true);
8038 ret->setCoords(coords);
8043 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8044 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8045 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8046 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8047 * New" mode are returned for each input mesh.
8048 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8049 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8050 * valid values [0,1,2], see zipConnectivityTraducer().
8051 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8052 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8053 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8055 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8056 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8057 * is no more needed.
8058 * \throw If \a meshes.size() == 0.
8059 * \throw If \a meshes[ *i* ] == NULL.
8060 * \throw If the meshes do not share the node coordinates array.
8061 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8062 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8063 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8064 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8066 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8068 //All checks are delegated to MergeUMeshesOnSameCoords
8069 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8071 corr.resize(meshes.size());
8072 std::size_t nbOfMeshes=meshes.size();
8074 const int *o2nPtr=o2n->getConstPointer();
8075 for(std::size_t i=0;i<nbOfMeshes;i++)
8077 DataArrayInt *tmp=DataArrayInt::New();
8078 int curNbOfCells=meshes[i]->getNumberOfCells();
8079 tmp->alloc(curNbOfCells,1);
8080 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8081 offset+=curNbOfCells;
8082 tmp->setName(meshes[i]->getName());
8089 * Makes all given meshes share the nodal connectivity array. The common connectivity
8090 * array is created by concatenating the connectivity arrays of all given meshes. All
8091 * the given meshes must be of the same space dimension but dimension of cells **can
8092 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8093 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8094 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8095 * \param [in,out] meshes - a vector of meshes to update.
8096 * \throw If any of \a meshes is NULL.
8097 * \throw If the coordinates array is not set in any of \a meshes.
8098 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8099 * \throw If \a meshes are of different space dimension.
8101 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8103 std::size_t sz=meshes.size();
8106 std::vector< const DataArrayDouble * > coords(meshes.size());
8107 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8108 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8112 (*it)->checkConnectivityFullyDefined();
8113 const DataArrayDouble *coo=(*it)->getCoords();
8118 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8119 oss << " has no coordinate array defined !";
8120 throw INTERP_KERNEL::Exception(oss.str().c_str());
8125 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8126 oss << " is null !";
8127 throw INTERP_KERNEL::Exception(oss.str().c_str());
8130 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8131 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8132 int offset=(*it)->getNumberOfNodes();
8133 (*it++)->setCoords(res);
8134 for(;it!=meshes.end();it++)
8136 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8137 (*it)->setCoords(res);
8138 (*it)->shiftNodeNumbersInConn(offset);
8139 offset+=oldNumberOfNodes;
8144 * Merges nodes coincident with a given precision within all given meshes that share
8145 * the nodal connectivity array. The given meshes **can be of different** mesh
8146 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8147 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8148 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8149 * \param [in,out] meshes - a vector of meshes to update.
8150 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8151 * \throw If any of \a meshes is NULL.
8152 * \throw If the \a meshes do not share the same node coordinates array.
8153 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8155 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8159 std::set<const DataArrayDouble *> s;
8160 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8163 s.insert((*it)->getCoords());
8166 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 !";
8167 throw INTERP_KERNEL::Exception(oss.str().c_str());
8172 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 !";
8173 throw INTERP_KERNEL::Exception(oss.str().c_str());
8175 const DataArrayDouble *coo=*(s.begin());
8179 DataArrayInt *comm,*commI;
8180 coo->findCommonTuples(eps,-1,comm,commI);
8181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8182 int oldNbOfNodes=coo->getNumberOfTuples();
8184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8185 if(oldNbOfNodes==newNbOfNodes)
8187 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8188 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8190 (*it)->renumberNodesInConn(o2n->getConstPointer());
8191 (*it)->setCoords(newCoords);
8196 * 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.
8197 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8198 * \param isQuad specifies the policy of connectivity.
8199 * @ret in/out parameter in which the result will be append
8201 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8203 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8204 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8205 ret.push_back(cm.getExtrudedType());
8206 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8209 case INTERP_KERNEL::NORM_POINT1:
8211 ret.push_back(connBg[1]);
8212 ret.push_back(connBg[1]+nbOfNodesPerLev);
8215 case INTERP_KERNEL::NORM_SEG2:
8217 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8218 ret.insert(ret.end(),conn,conn+4);
8221 case INTERP_KERNEL::NORM_SEG3:
8223 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8224 ret.insert(ret.end(),conn,conn+8);
8227 case INTERP_KERNEL::NORM_QUAD4:
8229 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8230 ret.insert(ret.end(),conn,conn+8);
8233 case INTERP_KERNEL::NORM_TRI3:
8235 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8236 ret.insert(ret.end(),conn,conn+6);
8239 case INTERP_KERNEL::NORM_TRI6:
8241 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,
8242 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8243 ret.insert(ret.end(),conn,conn+15);
8246 case INTERP_KERNEL::NORM_QUAD8:
8249 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8250 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8251 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8253 ret.insert(ret.end(),conn,conn+20);
8256 case INTERP_KERNEL::NORM_POLYGON:
8258 std::back_insert_iterator< std::vector<int> > ii(ret);
8259 std::copy(connBg+1,connEnd,ii);
8261 std::reverse_iterator<const int *> rConnBg(connEnd);
8262 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8263 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8264 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8265 for(std::size_t i=0;i<nbOfRadFaces;i++)
8268 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8269 std::copy(conn,conn+4,ii);
8274 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8279 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8281 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8284 double v[3]={0.,0.,0.};
8285 std::size_t sz=std::distance(begin,end);
8290 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];
8291 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8292 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8294 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8296 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8297 // SEG3 forming a circle):
8298 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8300 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8301 for(std::size_t j=0;j<sz;j++)
8303 if (j%2) // current point i is quadratic, next point i+1 is standard
8306 ip1 = (j+1)%sz; // ip1 = "i+1"
8308 else // current point i is standard, next point i+1 is quadratic
8313 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8314 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8315 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8317 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8323 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8325 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8327 std::vector<std::pair<int,int> > edges;
8328 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8329 const int *bgFace=begin;
8330 for(std::size_t i=0;i<nbOfFaces;i++)
8332 const int *endFace=std::find(bgFace+1,end,-1);
8333 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8334 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8336 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8337 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8339 edges.push_back(p1);
8343 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8347 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8349 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8351 double vec0[3],vec1[3];
8352 std::size_t sz=std::distance(begin,end);
8354 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8355 int nbOfNodes=(int)sz/2;
8356 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8357 const double *pt0=coords+3*begin[0];
8358 const double *pt1=coords+3*begin[nbOfNodes];
8359 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8360 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8363 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8365 std::size_t sz=std::distance(begin,end);
8366 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8367 std::size_t nbOfNodes(sz/2);
8368 std::copy(begin,end,(int *)tmp);
8369 for(std::size_t j=1;j<nbOfNodes;j++)
8371 begin[j]=tmp[nbOfNodes-j];
8372 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8376 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8378 std::size_t sz=std::distance(begin,end);
8380 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8381 double vec0[3],vec1[3];
8382 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8383 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];
8384 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;
8387 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8389 std::size_t sz=std::distance(begin,end);
8391 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8393 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8394 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8395 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8399 * 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 )
8400 * 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
8403 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8404 * \param [in] coords the coordinates with nb of components exactly equal to 3
8405 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8406 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8407 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8409 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8411 int nbFaces=std::count(begin+1,end,-1)+1;
8412 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8413 double *vPtr=v->getPointer();
8414 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8415 double *pPtr=p->getPointer();
8416 const int *stFaceConn=begin+1;
8417 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8419 const int *endFaceConn=std::find(stFaceConn,end,-1);
8420 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8421 stFaceConn=endFaceConn+1;
8423 pPtr=p->getPointer(); vPtr=v->getPointer();
8424 DataArrayInt *comm1=0,*commI1=0;
8425 v->findCommonTuples(eps,-1,comm1,commI1);
8426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8427 const int *comm1Ptr=comm1->getConstPointer();
8428 const int *commI1Ptr=commI1->getConstPointer();
8429 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8430 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8432 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8433 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8434 mm->finishInsertingCells();
8436 for(int i=0;i<nbOfGrps1;i++)
8438 int vecId=comm1Ptr[commI1Ptr[i]];
8439 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8440 DataArrayInt *comm2=0,*commI2=0;
8441 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8442 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8443 const int *comm2Ptr=comm2->getConstPointer();
8444 const int *commI2Ptr=commI2->getConstPointer();
8445 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8446 for(int j=0;j<nbOfGrps2;j++)
8448 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8450 res->insertAtTheEnd(begin,end);
8451 res->pushBackSilent(-1);
8455 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8457 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8458 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8459 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8460 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8463 const int *idsNodePtr=idsNode->getConstPointer();
8464 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];
8465 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8466 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8467 if(std::abs(norm)>eps)
8469 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8470 mm3->rotate(center,vec,angle);
8472 mm3->changeSpaceDimension(2);
8473 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8474 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8475 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8476 int nbOfCells=mm4->getNumberOfCells();
8477 for(int k=0;k<nbOfCells;k++)
8480 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8481 res->pushBackSilent(idsNodePtr[*work]);
8482 res->pushBackSilent(-1);
8487 res->popBackSilent();
8491 * 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
8492 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8494 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8495 * \param [in] coords coordinates expected to have 3 components.
8496 * \param [in] begin start of the nodal connectivity of the face.
8497 * \param [in] end end of the nodal connectivity (excluded) of the face.
8498 * \param [out] v the normalized vector of size 3
8499 * \param [out] p the pos of plane
8501 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8503 std::size_t nbPoints=std::distance(begin,end);
8505 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8506 double vec[3]={0.,0.,0.};
8508 bool refFound=false;
8509 for(;j<nbPoints-1 && !refFound;j++)
8511 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8512 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8513 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8514 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8518 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8521 for(std::size_t i=j;i<nbPoints-1;i++)
8524 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8525 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8526 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8527 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8530 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8531 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];
8532 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8535 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8536 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8540 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8544 * This method tries to obtain a well oriented polyhedron.
8545 * If the algorithm fails, an exception will be thrown.
8547 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8549 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8550 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8551 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8553 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8554 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8555 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8557 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8560 std::size_t smthChanged=0;
8561 for(std::size_t i=0;i<nbOfFaces;i++)
8563 endFace=std::find(bgFace+1,end,-1);
8564 nbOfEdgesInFace=std::distance(bgFace,endFace);
8568 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8570 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8571 std::pair<int,int> p2(p1.second,p1.first);
8572 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8573 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8574 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8579 std::reverse(bgFace+1,endFace);
8580 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8582 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8583 std::pair<int,int> p2(p1.second,p1.first);
8584 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8585 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8586 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8587 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8588 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8589 if(it!=edgesOK.end())
8592 edgesFinished.push_back(p1);
8595 edgesOK.push_back(p1);
8602 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8604 if(!edgesOK.empty())
8605 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8606 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8607 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8609 for(std::size_t i=0;i<nbOfFaces;i++)
8611 endFace=std::find(bgFace+1,end,-1);
8612 std::reverse(bgFace+1,endFace);
8618 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8620 int nbOfNodesExpected(skin->getNumberOfNodes());
8621 const int *n2oPtr(n2o->getConstPointer());
8622 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8623 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8624 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8625 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8626 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8627 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8628 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8629 if(nbOfNodesExpected<1)
8631 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8632 *work++=n2oPtr[prevNode];
8633 for(int i=1;i<nbOfNodesExpected;i++)
8635 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8637 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8638 conn.erase(prevNode);
8641 int curNode(*(conn.begin()));
8642 *work++=n2oPtr[curNode];
8643 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8644 shar.erase(prevCell);
8647 prevCell=*(shar.begin());
8651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8654 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8657 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8662 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8664 int nbOfNodesExpected(skin->getNumberOfNodes());
8665 int nbOfTurn(nbOfNodesExpected/2);
8666 const int *n2oPtr(n2o->getConstPointer());
8667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8668 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8669 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8670 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8671 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8672 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8673 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8674 if(nbOfNodesExpected<1)
8676 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8677 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8678 for(int i=1;i<nbOfTurn;i++)
8680 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8682 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8683 conn.erase(prevNode);
8686 int curNode(*(conn.begin()));
8687 *work=n2oPtr[curNode];
8688 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8689 shar.erase(prevCell);
8692 int curCell(*(shar.begin()));
8693 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8699 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8702 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8705 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8711 * This method makes the assumption spacedimension == meshdimension == 2.
8712 * This method works only for linear cells.
8714 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8716 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8718 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8720 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8721 int oldNbOfNodes(skin->getNumberOfNodes());
8722 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8723 int nbOfNodesExpected(skin->getNumberOfNodes());
8724 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8725 int nbCells(skin->getNumberOfCells());
8726 if(nbCells==nbOfNodesExpected)
8727 return buildUnionOf2DMeshLinear(skin,n2o);
8728 else if(2*nbCells==nbOfNodesExpected)
8729 return buildUnionOf2DMeshQuadratic(skin,n2o);
8731 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8735 * This method makes the assumption spacedimension == meshdimension == 3.
8736 * This method works only for linear cells.
8738 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8740 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8742 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8743 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8744 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8745 const int *conn=m->getNodalConnectivity()->getConstPointer();
8746 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8747 int nbOfCells=m->getNumberOfCells();
8748 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8749 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8752 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8753 for(int i=1;i<nbOfCells;i++)
8756 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8762 * \brief Creates a graph of cell neighbors
8763 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8764 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8766 * - index: 0 3 5 6 6
8767 * - value: 1 2 3 2 3 3
8768 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8769 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8771 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8773 checkConnectivityFullyDefined();
8775 int meshDim = this->getMeshDimension();
8776 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8777 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8778 this->getReverseNodalConnectivity(revConn,indexr);
8779 const int* indexr_ptr=indexr->getConstPointer();
8780 const int* revConn_ptr=revConn->getConstPointer();
8782 const ParaMEDMEM::DataArrayInt* index;
8783 const ParaMEDMEM::DataArrayInt* conn;
8784 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8785 index=this->getNodalConnectivityIndex();
8786 int nbCells=this->getNumberOfCells();
8787 const int* index_ptr=index->getConstPointer();
8788 const int* conn_ptr=conn->getConstPointer();
8790 //creating graph arcs (cell to cell relations)
8791 //arcs are stored in terms of (index,value) notation
8794 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8795 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8797 //warning here one node have less than or equal effective number of cell with it
8798 //but cell could have more than effective nodes
8799 //because other equals nodes in other domain (with other global inode)
8800 std::vector <int> cell2cell_index(nbCells+1,0);
8801 std::vector <int> cell2cell;
8802 cell2cell.reserve(3*nbCells);
8804 for (int icell=0; icell<nbCells;icell++)
8806 std::map<int,int > counter;
8807 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8809 int inode=conn_ptr[iconn];
8810 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8812 int icell2=revConn_ptr[iconnr];
8813 std::map<int,int>::iterator iter=counter.find(icell2);
8814 if (iter!=counter.end()) (iter->second)++;
8815 else counter.insert(std::make_pair(icell2,1));
8818 for (std::map<int,int>::const_iterator iter=counter.begin();
8819 iter!=counter.end(); iter++)
8820 if (iter->second >= meshDim)
8822 cell2cell_index[icell+1]++;
8823 cell2cell.push_back(iter->first);
8828 cell2cell_index[0]=0;
8829 for (int icell=0; icell<nbCells;icell++)
8830 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8832 //filling up index and value to create skylinearray structure
8833 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8838 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8839 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8841 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8845 for(int i=0;i<nbOfNodesInCell;i++)
8846 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8847 else if(spaceDim==2)
8849 for(int i=0;i<nbOfNodesInCell;i++)
8851 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8859 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8861 int nbOfCells=getNumberOfCells();
8863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8864 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};
8865 ofs << " <" << getVTKDataSetType() << ">\n";
8866 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8867 ofs << " <PointData>\n" << pointData << std::endl;
8868 ofs << " </PointData>\n";
8869 ofs << " <CellData>\n" << cellData << std::endl;
8870 ofs << " </CellData>\n";
8871 ofs << " <Points>\n";
8872 if(getSpaceDimension()==3)
8873 _coords->writeVTK(ofs,8,"Points",byteData);
8876 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8877 coo->writeVTK(ofs,8,"Points",byteData);
8879 ofs << " </Points>\n";
8880 ofs << " <Cells>\n";
8881 const int *cPtr=_nodal_connec->getConstPointer();
8882 const int *cIPtr=_nodal_connec_index->getConstPointer();
8883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8887 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8888 int szFaceOffsets=0,szConn=0;
8889 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8892 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8895 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8896 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8900 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8901 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8902 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8903 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8904 w4=std::copy(c.begin(),c.end(),w4);
8907 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8908 types->writeVTK(ofs,8,"UInt8","types",byteData);
8909 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8910 if(szFaceOffsets!=0)
8911 {//presence of Polyhedra
8912 connectivity->reAlloc(szConn);
8913 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8915 w1=faces->getPointer();
8916 for(int i=0;i<nbOfCells;i++)
8917 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8919 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8921 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8922 for(int j=0;j<nbFaces;j++)
8924 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8925 *w1++=(int)std::distance(w6,w5);
8926 w1=std::copy(w6,w5,w1);
8930 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8932 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8933 ofs << " </Cells>\n";
8934 ofs << " </Piece>\n";
8935 ofs << " </" << getVTKDataSetType() << ">\n";
8938 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8940 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8942 { stream << " Not set !"; return ; }
8943 stream << " Mesh dimension : " << _mesh_dim << ".";
8947 { stream << " No coordinates set !"; return ; }
8948 if(!_coords->isAllocated())
8949 { stream << " Coordinates set but not allocated !"; return ; }
8950 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8951 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8952 if(!_nodal_connec_index)
8953 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8954 if(!_nodal_connec_index->isAllocated())
8955 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8956 int lgth=_nodal_connec_index->getNumberOfTuples();
8957 int cpt=_nodal_connec_index->getNumberOfComponents();
8958 if(cpt!=1 || lgth<1)
8960 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8963 std::string MEDCouplingUMesh::getVTKDataSetType() const
8965 return std::string("UnstructuredGrid");
8968 std::string MEDCouplingUMesh::getVTKFileExtension() const
8970 return std::string("vtu");
8974 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8975 * returns a result mesh constituted by polygons.
8976 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8977 * all nodes from m2.
8978 * The meshes should be in 2D space. In
8979 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8981 * \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
8982 * 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)
8983 * \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
8984 * 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)
8985 * \param [in] eps - precision used to detect coincident mesh entities.
8986 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8987 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8988 * this array using decrRef() as it is no more needed.
8989 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8990 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8991 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8992 * any cell of \a m2. The caller is to delete this array using decrRef() as
8993 * it is no more needed.
8994 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8995 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8996 * is no more needed.
8997 * \throw If the coordinates array is not set in any of the meshes.
8998 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8999 * \throw If any of the meshes is not a 2D mesh in 2D space.
9001 * \sa conformize2D, mergeNodes
9003 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9004 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9007 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9008 m1->checkFullyDefined();
9009 m2->checkFullyDefined();
9010 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9011 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
9013 // Step 1: compute all edge intersections (new nodes)
9014 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9015 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9016 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9017 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9018 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9019 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9020 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9021 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9022 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9023 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9025 // Step 2: re-order newly created nodes according to the ordering found in m2
9026 std::vector< std::vector<int> > intersectEdge2;
9027 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9028 subDiv2.clear(); dd5=0; dd6=0;
9031 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9032 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9033 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9034 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9036 // Step 4: Prepare final result:
9037 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9038 addCooDa->alloc((int)(addCoo.size())/2,2);
9039 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9040 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9041 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9042 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9043 std::vector<const DataArrayDouble *> coordss(4);
9044 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9045 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9046 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9051 ret->setConnectivity(conn,connI,true);
9052 ret->setCoords(coo);
9053 cellNb1=c1.retn(); cellNb2=c2.retn();
9059 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9061 if(candidates.empty())
9063 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9065 const std::vector<int>& pool(intersectEdge1[*it]);
9066 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9067 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9072 tmp[0]=stop; tmp[1]=start;
9073 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9082 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,
9083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9085 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9086 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9087 int nCells(mesh1D->getNumberOfCells());
9088 if(nCells!=(int)intersectEdge2.size())
9089 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9090 const DataArrayDouble *coo2(mesh1D->getCoords());
9091 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9092 const double *coo2Ptr(coo2->begin());
9093 int offset1(coords1->getNumberOfTuples());
9094 int offset2(offset1+coo2->getNumberOfTuples());
9095 int offset3(offset2+addCoo.size()/2);
9096 std::vector<double> addCooQuad;
9097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9098 int tmp[4],cicnt(0),kk(0);
9099 for(int i=0;i<nCells;i++)
9101 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9102 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9103 const std::vector<int>& subEdges(intersectEdge2[i]);
9104 int nbSubEdge(subEdges.size()/2);
9105 for(int j=0;j<nbSubEdge;j++,kk++)
9107 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));
9108 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9109 INTERP_KERNEL::Edge *e2Ptr(e2);
9110 std::map<int,int>::const_iterator itm;
9111 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9113 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9114 itm=mergedNodes.find(subEdges[2*j]);
9115 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9116 itm=mergedNodes.find(subEdges[2*j+1]);
9117 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9118 tmp[3]=offset3+(int)addCooQuad.size()/2;
9120 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9122 cOut->insertAtTheEnd(tmp,tmp+4);
9123 ciOut->pushBackSilent(cicnt);
9127 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9128 itm=mergedNodes.find(subEdges[2*j]);
9129 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9130 itm=mergedNodes.find(subEdges[2*j+1]);
9131 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9133 cOut->insertAtTheEnd(tmp,tmp+3);
9134 ciOut->pushBackSilent(cicnt);
9137 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9139 idsInRetColinear->pushBackSilent(kk);
9140 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9145 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9146 ret->setConnectivity(cOut,ciOut,true);
9147 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9148 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9149 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9150 std::vector<const DataArrayDouble *> coordss(4);
9151 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9152 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9153 ret->setCoords(arr);
9157 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9159 std::vector<int> allEdges;
9160 for(const int *it2(descBg);it2!=descEnd;it2++)
9162 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9164 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9166 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9168 std::size_t nb(allEdges.size());
9170 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9171 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9172 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9173 ret->setCoords(coords);
9174 ret->allocateCells(1);
9175 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9176 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9177 connOut[kk]=allEdges[2*kk];
9178 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9182 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9184 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9185 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9187 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9188 if(sz!=std::distance(descBg,descEnd))
9189 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9190 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9191 std::vector<int> allEdges,centers;
9192 const double *coordsPtr(coords->begin());
9193 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9194 int offset(coords->getNumberOfTuples());
9195 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9197 INTERP_KERNEL::NormalizedCellType typeOfSon;
9198 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9199 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9201 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9203 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9205 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9207 {//the current edge has been subsplit -> create corresponding centers.
9208 std::size_t nbOfCentersToAppend(edge1.size()/2);
9209 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9210 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9211 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9212 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9215 const double *aa(coordsPtr+2*(*it3++));
9216 const double *bb(coordsPtr+2*(*it3++));
9217 ee->getMiddleOfPoints(aa,bb,tmpp);
9218 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9219 centers.push_back(offset+k);
9223 std::size_t nb(allEdges.size());
9225 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9226 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9227 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9229 ret->setCoords(coords);
9232 addCoo->rearrange(2);
9233 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9234 ret->setCoords(addCoo);
9236 ret->allocateCells(1);
9237 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9238 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9239 connOut[kk]=allEdges[2*kk];
9240 connOut.insert(connOut.end(),centers.begin(),centers.end());
9241 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9246 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9249 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9251 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9253 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9254 if(!cm.isQuadratic())
9255 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9257 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9260 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9263 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9265 const INTERP_KERNEL::Edge *ee(*it);
9266 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9270 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9273 const double *coo(mesh2D->getCoords()->begin());
9274 std::size_t sz(conn.size());
9275 std::vector<double> addCoo;
9276 std::vector<int> conn2(conn);
9277 int offset(mesh2D->getNumberOfNodes());
9278 for(std::size_t i=0;i<sz;i++)
9281 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9282 addCoo.insert(addCoo.end(),tmp,tmp+2);
9283 conn2.push_back(offset+(int)i);
9285 mesh2D->getCoords()->rearrange(1);
9286 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9287 mesh2D->getCoords()->rearrange(2);
9288 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9293 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9295 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9296 * a set of edges defined in \a splitMesh1D.
9298 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9299 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9301 std::size_t nb(edge1Bis.size()/2);
9302 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9303 int iEnd(splitMesh1D->getNumberOfCells());
9305 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9307 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9308 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9309 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9312 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9313 out0.resize(1); out1.resize(1);
9314 std::vector<int>& connOut(out0[0]);
9315 connOut.resize(nbOfEdgesOf2DCellSplit);
9316 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9317 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9318 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9320 connOut[kk]=edge1Bis[2*kk];
9321 edgesPtr[kk]=edge1BisPtr[2*kk];
9326 // [i,iEnd[ contains the
9327 out0.resize(2); out1.resize(2);
9328 std::vector<int>& connOutLeft(out0[0]);
9329 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9330 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9331 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9332 for(std::size_t k=ii;k<jj+1;k++)
9333 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9334 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9335 for(int ik=0;ik<iEnd;ik++)
9337 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9338 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9341 for(int ik=iEnd-1;ik>=0;ik--)
9342 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9343 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9344 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9345 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9346 for(int ik=0;ik<iEnd;ik++)
9347 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9348 eright.insert(eright.end(),ees.begin(),ees.end());
9360 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9362 std::vector<int> _edges;
9363 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9366 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9368 std::size_t nbe(edges.size());
9369 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9370 for(std::size_t i=0;i<nbe;i++)
9372 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9373 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9375 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9376 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9377 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9383 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9384 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9385 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9386 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9387 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9391 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9392 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9397 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9399 const MEDCouplingUMesh *mesh(_mesh);
9405 { _left++; _right++; return ; }
9408 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9409 if((isLeft && isRight) || (!isLeft && !isRight))
9410 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9421 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9422 if((isLeft && isRight) || (!isLeft && !isRight))
9423 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9438 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9440 const MEDCouplingUMesh *mesh(_mesh);
9443 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9446 {// not fully splitting cell case
9447 if(mesh2D->getNumberOfCells()==1)
9448 {//little optimization. 1 cell no need to find in which cell mesh is !
9449 neighbors[0]=offset; neighbors[1]=offset;
9454 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9455 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9457 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9458 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9463 class VectorOfCellInfo
9466 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9467 std::size_t size() const { return _pool.size(); }
9468 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9469 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);
9470 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9471 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9472 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9473 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9475 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9476 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9477 const CellInfo& get(int pos) const;
9478 CellInfo& get(int pos);
9480 std::vector<CellInfo> _pool;
9481 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9482 std::vector<EdgeInfo> _edge_info;
9485 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9487 _pool[0]._edges=edges;
9488 _pool[0]._edges_ptr=edgesPtr;
9491 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9494 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9497 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9499 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9500 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9501 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9504 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)
9506 get(pos);//to check pos
9507 bool isFast(pos==0 && _pool.size()==1);
9508 std::size_t sz(edges.size());
9509 // dealing with edges
9511 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9513 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9515 std::vector<CellInfo> pool(_pool.size()-1+sz);
9516 for(int i=0;i<pos;i++)
9518 for(std::size_t j=0;j<sz;j++)
9519 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9520 for(int i=pos+1;i<(int)_pool.size();i++)
9521 pool[i+sz-1]=_pool[i];
9525 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9533 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9536 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9540 if(pos<_ze_mesh->getNumberOfCells()-1)
9542 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9545 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9546 for(std::size_t j=0;j<ms2.size();j++)
9548 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9551 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9553 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9556 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9559 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9561 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9563 if((*it).isInMyRange(pos))
9566 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9569 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9571 get(pos);//to check;
9572 if(_edge_info.empty())
9574 std::size_t sz(_edge_info.size()-1);
9575 for(std::size_t i=0;i<sz;i++)
9576 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9579 const CellInfo& VectorOfCellInfo::get(int pos) const
9581 if(pos<0 || pos>=(int)_pool.size())
9582 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9586 CellInfo& VectorOfCellInfo::get(int pos)
9588 if(pos<0 || pos>=(int)_pool.size())
9589 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9595 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9596 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9598 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9600 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9602 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9604 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9607 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9608 if(nbCellsInSplitMesh1D==0)
9609 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9610 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9611 std::size_t nb(allEdges.size()),jj;
9613 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9614 std::vector<int> edge1Bis(nb*2);
9615 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9616 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9617 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9618 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9619 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9621 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9622 int *idsLeftRightPtr(idsLeftRight->getPointer());
9623 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9624 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9625 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9627 for(;iEnd<nbCellsInSplitMesh1D;)
9629 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9635 if(iEnd<nbCellsInSplitMesh1D)
9638 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9639 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9641 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9642 retTmp->setCoords(splitMesh1D->getCoords());
9643 retTmp->allocateCells();
9645 std::vector< std::vector<int> > out0;
9646 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9648 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9649 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9650 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9651 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9655 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9656 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9657 return pool.getZeMesh().retn();
9660 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9661 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9664 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9666 std::vector<int> allEdges;
9667 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9668 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9670 int edgeId(std::abs(*it)-1);
9671 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9672 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9673 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9675 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9677 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9678 std::size_t sz(edge1.size());
9679 for(std::size_t cnt=0;cnt<sz;cnt++)
9680 allEdgesPtr.push_back(ee);
9683 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9686 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9688 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9689 {//easy case comparison not
9690 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9692 else if(typ1.isQuadratic() && typ2.isQuadratic())
9694 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9697 if(conn1[2]==conn2[2])
9699 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9700 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9704 {//only one is quadratic
9705 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9708 const double *a(0),*bb(0),*be(0);
9709 if(typ1.isQuadratic())
9711 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9715 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9717 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9718 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9724 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9725 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9727 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9729 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9731 if(candidatesIn2DEnd==candidatesIn2DBg)
9732 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9733 const double *coo(mesh2DSplit->getCoords()->begin());
9734 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9735 return *candidatesIn2DBg;
9736 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9737 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9738 if(cellIdInMesh1DSplitRelative<0)
9739 cur1D->changeOrientationOfCells();
9740 const int *c1D(cur1D->getNodalConnectivity()->begin());
9741 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9742 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9744 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9745 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9746 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9747 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9748 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9749 for(unsigned it2=0;it2<sz;it2++)
9751 INTERP_KERNEL::NormalizedCellType typeOfSon;
9752 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9753 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9754 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9758 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9764 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9765 * 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
9766 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9767 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9769 * \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
9770 * 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)
9771 * \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
9772 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9773 * \param [in] eps - precision used to perform intersections and localization operations.
9774 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9775 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9776 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9777 * 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.
9778 * \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
9779 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9780 * 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.
9782 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9784 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9786 if(!mesh2D || !mesh1D)
9787 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9788 mesh2D->checkFullyDefined();
9789 mesh1D->checkFullyDefined();
9790 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9791 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9792 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9793 // Step 1: compute all edge intersections (new nodes)
9794 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9795 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9796 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9797 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9799 // Build desc connectivity
9800 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9801 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9802 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9803 std::map<int,int> mergedNodes;
9804 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9805 // use mergeNodes to fix intersectEdge1
9806 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9808 std::size_t n((*it0).size()/2);
9809 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9810 std::map<int,int>::const_iterator it1;
9811 it1=mergedNodes.find(eltStart);
9812 if(it1!=mergedNodes.end())
9813 (*it0)[0]=(*it1).second;
9814 it1=mergedNodes.find(eltEnd);
9815 if(it1!=mergedNodes.end())
9816 (*it0)[2*n-1]=(*it1).second;
9819 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9820 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9821 // Step 2: re-order newly created nodes according to the ordering found in m2
9822 std::vector< std::vector<int> > intersectEdge2;
9823 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9825 // Step 3: compute splitMesh1D
9826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9827 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9828 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9829 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9832 // deal with cells in mesh2D that are not cut but only some of their edges are
9833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9834 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9835 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9836 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
9837 if(!idsInDesc2DToBeRefined->empty())
9839 DataArrayInt *out0(0),*outi0(0);
9840 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9843 out0s=out0s->buildUnique();
9847 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9848 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9850 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9851 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9852 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9853 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9854 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9855 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9857 if((DataArrayInt *)out0s)
9858 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9859 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9860 // OK all is ready to insert in ret2 mesh
9861 if(!untouchedCells->empty())
9862 {// the most easy part, cells in mesh2D not impacted at all
9863 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9864 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9865 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9867 if((DataArrayInt *)out0s)
9868 {// here dealing with cells in out0s but not in cellsToBeModified
9869 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9870 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9871 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9873 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9874 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9876 int offset(ret2->getNumberOfTuples());
9877 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9879 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9880 int kk(0),*ret3ptr(partOfRet3->getPointer());
9881 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9883 int faceId(std::abs(*it)-1);
9884 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9886 int tmp(fewModifiedCells->locateValue(*it2));
9889 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9890 ret3ptr[2*kk]=tmp+offset;
9891 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9892 ret3ptr[2*kk+1]=tmp+offset;
9895 {//the current edge is shared by a 2D cell that will be split just after
9896 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9897 ret3ptr[2*kk]=-(*it2+1);
9898 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9899 ret3ptr[2*kk+1]=-(*it2+1);
9903 m1Desc->setCoords(ret1->getCoords());
9904 ret1NonCol->setCoords(ret1->getCoords());
9905 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9906 if(!outMesh2DSplit.empty())
9908 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9909 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9910 (*itt)->setCoords(da);
9913 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9914 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9917 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9918 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9919 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9921 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));
9922 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9923 outMesh2DSplit.push_back(splitOfOneCell);
9924 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9925 ret2->pushBackSilent(*it);
9928 std::size_t nbOfMeshes(outMesh2DSplit.size());
9929 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9930 for(std::size_t i=0;i<nbOfMeshes;i++)
9931 tmp[i]=outMesh2DSplit[i];
9933 ret1->getCoords()->setInfoOnComponents(compNames);
9934 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9935 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9937 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9938 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9940 int old2DCellId(-ret3->getIJ(*it,0)-1);
9941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9942 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
9944 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9947 splitMesh1D=ret1.retn();
9948 splitMesh2D=ret2D.retn();
9949 cellIdInMesh2D=ret2.retn();
9950 cellIdInMesh1D=ret3.retn();
9954 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9955 * (newly created) nodes corresponding to the edge intersections.
9957 * @param[out] cr, crI connectivity of the resulting mesh
9958 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9959 * TODO: describe input parameters
9961 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9962 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9963 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9964 const std::vector<double>& addCoords,
9965 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9967 static const int SPACEDIM=2;
9968 const double *coo1(m1->getCoords()->getConstPointer());
9969 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9970 int offset1(m1->getNumberOfNodes());
9971 const double *coo2(m2->getCoords()->getConstPointer());
9972 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9973 int offset2(offset1+m2->getNumberOfNodes());
9974 int offset3(offset2+((int)addCoords.size())/2);
9975 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9976 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9977 // Here a BBTree on 2D-cells, not on segments:
9978 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9979 int ncell1(m1->getNumberOfCells());
9981 for(int i=0;i<ncell1;i++)
9983 std::vector<int> candidates2;
9984 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9985 std::map<INTERP_KERNEL::Node *,int> mapp;
9986 std::map<int,INTERP_KERNEL::Node *> mappRev;
9987 INTERP_KERNEL::QuadraticPolygon pol1;
9988 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9989 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9990 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9991 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9992 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9993 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9994 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9996 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
9997 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9998 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9999 for(it1.first();!it1.finished();it1.next())
10000 edges1.insert(it1.current()->getPtr());
10002 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10003 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10005 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10007 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10008 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10009 // Complete mapping with elements coming from the current cell it2 in mesh2:
10010 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10011 // pol2 is the new QP in the final merged result.
10012 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10013 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10016 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10018 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10019 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10020 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10021 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10023 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10024 // by m2 but that we still want to keep in the final result.
10025 if(!edges1.empty())
10029 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10031 catch(INTERP_KERNEL::Exception& e)
10033 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();
10034 throw INTERP_KERNEL::Exception(oss.str().c_str());
10037 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10038 (*it).second->decrRef();
10043 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10044 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10045 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10046 * The caller is to deal with the resulting DataArrayInt.
10047 * \throw If the coordinate array is not set.
10048 * \throw If the nodal connectivity of the cells is not defined.
10049 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10050 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10052 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10054 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10056 checkFullyDefined();
10057 if(getMeshDimension()!=1)
10058 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10060 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10062 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10063 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10064 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10065 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10066 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10067 const int * dsi(_dsi->getConstPointer());
10068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10070 if (dsii->getNumberOfTuples())
10071 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10073 int nc(getNumberOfCells());
10074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10075 result->alloc(nc,1);
10077 // set of edges not used so far
10078 std::set<int> edgeSet;
10079 for (int i=0; i<nc; edgeSet.insert(i), i++);
10083 // while we have points with only one neighbor segments
10086 std::list<int> linePiece;
10087 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10088 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10090 // Fill the list forward (resp. backward) from the start segment:
10091 int activeSeg = startSeg;
10092 int prevPointId = -20;
10094 while (!edgeSet.empty())
10096 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10099 linePiece.push_back(activeSeg);
10101 linePiece.push_front(activeSeg);
10102 edgeSet.erase(activeSeg);
10105 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10106 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10107 if (dsi[ptId] == 1) // hitting the end of the line
10109 prevPointId = ptId;
10110 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10111 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10114 // Done, save final piece into DA:
10115 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10116 newIdx += linePiece.size();
10118 // identify next valid start segment (one which is not consumed)
10119 if(!edgeSet.empty())
10120 startSeg = *(edgeSet.begin());
10122 while (!edgeSet.empty());
10123 return result.retn();
10128 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10130 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10131 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10133 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10134 int v((*it).second);
10135 if(v==forbVal0 || v==forbVal1)
10137 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10138 isect.push_back(v);
10141 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10146 bool presenceOfOn(false);
10147 for(int i=0;i<sz;i++)
10149 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10150 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10152 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10153 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10155 return presenceOfOn;
10161 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10162 * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10163 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10164 * a minimal creation of new nodes is wanted.
10165 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10166 * nodes if a SEG3 is split without information of middle.
10167 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10168 * avoid to have a non conform mesh.
10170 * \return int - the number of new nodes created (in most of cases 0).
10172 * \throw If \a this is not coherent.
10173 * \throw If \a this has not spaceDim equal to 2.
10174 * \throw If \a this has not meshDim equal to 2.
10175 * \throw If some subcells needed to be split are orphan.
10176 * \sa MEDCouplingUMesh::conformize2D
10178 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10180 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10182 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10183 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10184 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10185 if(midOpt==0 && midOptI==0)
10187 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10190 else if(midOpt!=0 && midOptI!=0)
10191 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10193 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10197 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10198 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10199 * 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
10200 * 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).
10201 * 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.
10203 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10204 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10206 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10207 * This method expects that all nodes in \a this are not closer than \a eps.
10208 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10210 * \param [in] eps the relative error to detect merged edges.
10211 * \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
10212 * that the user is expected to deal with.
10214 * \throw If \a this is not coherent.
10215 * \throw If \a this has not spaceDim equal to 2.
10216 * \throw If \a this has not meshDim equal to 2.
10217 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10219 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10221 static const int SPACEDIM=2;
10223 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10224 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10225 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10226 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10227 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10228 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10229 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10230 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10231 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10232 std::vector<double> addCoo;
10233 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10234 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10235 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10236 for(int i=0;i<nDescCell;i++)
10238 std::vector<int> candidates;
10239 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10240 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10243 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10244 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10245 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10246 INTERP_KERNEL::MergePoints merge;
10247 INTERP_KERNEL::QuadraticPolygon c1,c2;
10248 e1->intersectWith(e2,merge,c1,c2);
10249 e1->decrRef(); e2->decrRef();
10250 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10251 overlapEdge[i].push_back(*it);
10252 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10253 overlapEdge[*it].push_back(i);
10256 // splitting done. sort intersect point in intersectEdge.
10257 std::vector< std::vector<int> > middle(nDescCell);
10258 int nbOf2DCellsToBeSplit(0);
10259 bool middleNeedsToBeUsed(false);
10260 std::vector<bool> cells2DToTreat(nDescCell,false);
10261 for(int i=0;i<nDescCell;i++)
10263 std::vector<int>& isect(intersectEdge[i]);
10264 int sz((int)isect.size());
10267 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10268 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10269 e->sortSubNodesAbs(coords,isect);
10274 int idx0(rdi[i]),idx1(rdi[i+1]);
10276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10277 if(!cells2DToTreat[rd[idx0]])
10279 cells2DToTreat[rd[idx0]]=true;
10280 nbOf2DCellsToBeSplit++;
10282 // try to reuse at most eventual 'middle' of SEG3
10283 std::vector<int>& mid(middle[i]);
10284 mid.resize(sz+1,-1);
10285 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10287 middleNeedsToBeUsed=true;
10288 const std::vector<int>& candidates(overlapEdge[i]);
10289 std::vector<int> trueCandidates;
10290 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10291 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10292 trueCandidates.push_back(*itc);
10293 int stNode(c[ci[i]+1]),endNode(isect[0]);
10294 for(int j=0;j<sz+1;j++)
10296 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10298 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10299 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10300 { mid[j]=*itc; break; }
10303 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10309 if(nbOf2DCellsToBeSplit==0)
10312 int *retPtr(ret->getPointer());
10313 for(int i=0;i<nCell;i++)
10314 if(cells2DToTreat[i])
10317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10318 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10319 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10320 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10321 if(middleNeedsToBeUsed)
10322 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10324 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10325 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.
10326 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10328 bool areNodesMerged; int newNbOfNodes;
10329 if(nbOfNodesCreated!=0)
10330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10336 * 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.
10337 * 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).
10338 * 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
10339 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10340 * 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
10341 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10343 * 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
10344 * using new instance, idem for coordinates.
10346 * 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.
10348 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10350 * \throw If \a this is not coherent.
10351 * \throw If \a this has not spaceDim equal to 2.
10352 * \throw If \a this has not meshDim equal to 2.
10354 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10356 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10360 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10362 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10363 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10364 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10365 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10367 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10368 const double *coords(_coords->begin());
10369 int *newciptr(newci->getPointer());
10370 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10372 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10373 ret->pushBackSilent(i);
10374 newciptr[1]=newc->getNumberOfTuples();
10379 if(!appendedCoords->empty())
10381 appendedCoords->rearrange(2);
10382 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10384 setCoords(newCoords);
10387 setConnectivity(newc,newci,true);
10392 * \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.
10393 * 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.
10394 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10395 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10396 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10397 * \param [out] addCoo - nodes to be append at the end
10398 * \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.
10400 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10401 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)
10403 static const int SPACEDIM=2;
10404 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10405 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10406 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10407 // Build BB tree of all edges in the tool mesh (second mesh)
10408 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10409 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10410 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10411 intersectEdge1.resize(nDescCell1);
10412 colinear2.resize(nDescCell2);
10413 subDiv2.resize(nDescCell2);
10414 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10416 std::vector<int> candidates1(1);
10417 int offset1(m1Desc->getNumberOfNodes());
10418 int offset2(offset1+m2Desc->getNumberOfNodes());
10419 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10421 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10422 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10423 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10425 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10426 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10427 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10429 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10430 // 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
10431 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10432 std::set<INTERP_KERNEL::Node *> nodes;
10433 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10434 std::size_t szz(nodes.size());
10435 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10436 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10437 for(std::size_t iii=0;iii<szz;iii++,itt++)
10438 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10439 // end of protection
10440 // Performs egde cutting:
10441 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10446 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10447 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10452 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10453 * It builds the descending connectivity of the two meshes, and then using a binary tree
10454 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10455 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10457 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10458 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10459 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10460 std::vector<double>& addCoo,
10461 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10463 // Build desc connectivity
10464 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10465 desc2=DataArrayInt::New();
10466 descIndx2=DataArrayInt::New();
10467 revDesc2=DataArrayInt::New();
10468 revDescIndx2=DataArrayInt::New();
10469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10471 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10472 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10473 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10474 std::map<int,int> notUsedMap;
10475 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10476 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10477 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10481 * This method performs the 2nd step of Partition of 2D mesh.
10482 * This method has 4 inputs :
10483 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10484 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10485 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10486 * 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'
10487 * Nodes end up lying consecutively on a cutted edge.
10488 * \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.
10489 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10490 * \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.
10491 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10492 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10494 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10495 const std::vector<double>& addCoo,
10496 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10498 int offset1=m1->getNumberOfNodes();
10499 int ncell=m2->getNumberOfCells();
10500 const int *c=m2->getNodalConnectivity()->getConstPointer();
10501 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10502 const double *coo=m2->getCoords()->getConstPointer();
10503 const double *cooBis=m1->getCoords()->getConstPointer();
10504 int offset2=offset1+m2->getNumberOfNodes();
10505 intersectEdge.resize(ncell);
10506 for(int i=0;i<ncell;i++,cI++)
10508 const std::vector<int>& divs=subDiv[i];
10509 int nnode=cI[1]-cI[0]-1;
10510 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10511 std::map<INTERP_KERNEL::Node *, int> mapp22;
10512 for(int j=0;j<nnode;j++)
10514 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10515 int nnid=c[(*cI)+j+1];
10516 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10517 mapp22[nn]=nnid+offset1;
10519 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10520 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10521 ((*it).second.first)->decrRef();
10522 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10523 std::map<INTERP_KERNEL::Node *,int> mapp3;
10524 for(std::size_t j=0;j<divs.size();j++)
10527 INTERP_KERNEL::Node *tmp=0;
10529 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10530 else if(id<offset2)
10531 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10533 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10537 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10538 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10545 * 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).
10546 * 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
10547 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10548 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10549 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10550 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10551 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10552 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10553 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10554 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10555 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10556 * \param [out] cut3DSuf input/output param.
10558 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10559 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10560 const int *desc, const int *descIndx,
10561 std::vector< std::pair<int,int> >& cut3DSurf)
10563 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10564 int nbOf3DSurfCell=(int)cut3DSurf.size();
10565 for(int i=0;i<nbOf3DSurfCell;i++)
10567 std::vector<int> res;
10568 int offset=descIndx[i];
10569 int nbOfSeg=descIndx[i+1]-offset;
10570 for(int j=0;j<nbOfSeg;j++)
10572 int edgeId=desc[offset+j];
10573 int status=cut3DCurve[edgeId];
10577 res.push_back(status);
10580 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10581 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10589 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10595 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10596 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10599 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10603 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10608 {// case when plane is on a multi colinear edge of a polyhedron
10609 if((int)res.size()==2*nbOfSeg)
10611 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10614 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10621 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10622 * 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).
10623 * 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
10624 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10625 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10626 * \param desc is the descending connectivity 3D->3DSurf
10627 * \param descIndx is the descending connectivity index 3D->3DSurf
10629 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10630 const int *desc, const int *descIndx,
10631 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10633 checkFullyDefined();
10634 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10635 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10636 const int *nodal3D=_nodal_connec->getConstPointer();
10637 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10638 int nbOfCells=getNumberOfCells();
10639 for(int i=0;i<nbOfCells;i++)
10641 std::map<int, std::set<int> > m;
10642 int offset=descIndx[i];
10643 int nbOfFaces=descIndx[i+1]-offset;
10646 for(int j=0;j<nbOfFaces;j++)
10648 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10649 if(p.first!=-1 && p.second!=-1)
10653 start=p.first; end=p.second;
10654 m[p.first].insert(p.second);
10655 m[p.second].insert(p.first);
10659 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10660 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10661 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10662 INTERP_KERNEL::NormalizedCellType cmsId;
10663 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10664 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10665 for(unsigned k=0;k<nbOfNodesSon;k++)
10667 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10668 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10675 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10679 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10680 const std::set<int>& s=(*it).second;
10681 std::set<int> s2; s2.insert(prev);
10683 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10686 int val=*s3.begin();
10687 conn.push_back(start);
10694 conn.push_back(end);
10697 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10698 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10699 cellIds->pushBackSilent(i);
10705 * 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
10706 * 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
10707 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10708 * 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
10709 * 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.
10711 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10713 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10715 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10718 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10719 if(cm.getDimension()==2)
10721 const int *node=nodalConnBg+1;
10722 int startNode=*node++;
10723 double refX=coords[2*startNode];
10724 for(;node!=nodalConnEnd;node++)
10726 if(coords[2*(*node)]<refX)
10729 refX=coords[2*startNode];
10732 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10736 double angle0=-M_PI/2;
10741 double angleNext=0.;
10742 while(nextNode!=startNode)
10746 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10748 if(*node!=tmpOut.back() && *node!=prevNode)
10750 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10751 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10756 res=angle0-angleM+2.*M_PI;
10765 if(nextNode!=startNode)
10767 angle0=angleNext-M_PI;
10770 prevNode=tmpOut.back();
10771 tmpOut.push_back(nextNode);
10774 std::vector<int> tmp3(2*(sz-1));
10775 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10776 std::copy(nodalConnBg+1,nodalConnEnd,it);
10777 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10779 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10782 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10784 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10789 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10790 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10798 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10802 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10803 * 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.
10805 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10806 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10807 * \param [in,out] arr array in which the remove operation will be done.
10808 * \param [in,out] arrIndx array in the remove operation will modify
10809 * \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])
10810 * \return true if \b arr and \b arrIndx have been modified, false if not.
10812 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10814 if(!arrIndx || !arr)
10815 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10816 if(offsetForRemoval<0)
10817 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10818 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10819 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10820 int *arrIPtr=arrIndx->getPointer();
10822 int previousArrI=0;
10823 const int *arrPtr=arr->getConstPointer();
10824 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10825 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10827 if(*arrIPtr-previousArrI>offsetForRemoval)
10829 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10831 if(s.find(*work)==s.end())
10832 arrOut.push_back(*work);
10835 previousArrI=*arrIPtr;
10836 *arrIPtr=(int)arrOut.size();
10838 if(arr->getNumberOfTuples()==(int)arrOut.size())
10840 arr->alloc((int)arrOut.size(),1);
10841 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10846 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10847 * (\ref numbering-indirect).
10848 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10849 * The selection of extraction is done standardly in new2old format.
10850 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10852 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10853 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10854 * \param [in] arrIn arr origin array from which the extraction will be done.
10855 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10856 * \param [out] arrOut the resulting array
10857 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10858 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10860 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10861 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10863 if(!arrIn || !arrIndxIn)
10864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10865 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10866 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10867 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10868 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10869 const int *arrInPtr=arrIn->getConstPointer();
10870 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10871 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10874 int maxSizeOfArr=arrIn->getNumberOfTuples();
10875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10877 arrIo->alloc((int)(sz+1),1);
10878 const int *idsIt=idsOfSelectBg;
10879 int *work=arrIo->getPointer();
10882 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10884 if(*idsIt>=0 && *idsIt<nbOfGrps)
10885 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10888 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10889 throw INTERP_KERNEL::Exception(oss.str().c_str());
10895 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10896 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10897 throw INTERP_KERNEL::Exception(oss.str().c_str());
10900 arro->alloc(lgth,1);
10901 work=arro->getPointer();
10902 idsIt=idsOfSelectBg;
10903 for(std::size_t i=0;i<sz;i++,idsIt++)
10905 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10906 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10909 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10910 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10911 throw INTERP_KERNEL::Exception(oss.str().c_str());
10914 arrOut=arro.retn();
10915 arrIndexOut=arrIo.retn();
10919 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10920 * (\ref numbering-indirect).
10921 * 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 ).
10922 * The selection of extraction is done standardly in new2old format.
10923 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10925 * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10926 * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10927 * \param [in] idsOfSelectStep
10928 * \param [in] arrIn arr origin array from which the extraction will be done.
10929 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10930 * \param [out] arrOut the resulting array
10931 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10932 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10934 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10935 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10937 if(!arrIn || !arrIndxIn)
10938 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10939 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10940 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10941 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10942 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10943 const int *arrInPtr=arrIn->getConstPointer();
10944 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10945 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10948 int maxSizeOfArr=arrIn->getNumberOfTuples();
10949 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10951 arrIo->alloc((int)(sz+1),1);
10952 int idsIt=idsOfSelectStart;
10953 int *work=arrIo->getPointer();
10956 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10958 if(idsIt>=0 && idsIt<nbOfGrps)
10959 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10962 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10963 throw INTERP_KERNEL::Exception(oss.str().c_str());
10969 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10970 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10971 throw INTERP_KERNEL::Exception(oss.str().c_str());
10974 arro->alloc(lgth,1);
10975 work=arro->getPointer();
10976 idsIt=idsOfSelectStart;
10977 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10979 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10980 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10983 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10984 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10985 throw INTERP_KERNEL::Exception(oss.str().c_str());
10988 arrOut=arro.retn();
10989 arrIndexOut=arrIo.retn();
10993 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10994 * 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
10995 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10996 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10998 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10999 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11000 * \param [in] arrIn arr origin array from which the extraction will be done.
11001 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11002 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11003 * \param [in] srcArrIndex index array of \b srcArr
11004 * \param [out] arrOut the resulting array
11005 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11007 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11009 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11010 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11011 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11013 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11014 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11017 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11018 std::vector<bool> v(nbOfTuples,true);
11020 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11021 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11022 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11024 if(*it>=0 && *it<nbOfTuples)
11027 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11031 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11032 throw INTERP_KERNEL::Exception(oss.str().c_str());
11035 srcArrIndexPtr=srcArrIndex->getConstPointer();
11036 arrIo->alloc(nbOfTuples+1,1);
11037 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11038 const int *arrInPtr=arrIn->getConstPointer();
11039 const int *srcArrPtr=srcArr->getConstPointer();
11040 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11041 int *arroPtr=arro->getPointer();
11042 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11046 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11047 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11051 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11052 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11053 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11056 arrOut=arro.retn();
11057 arrIndexOut=arrIo.retn();
11061 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11062 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11064 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11065 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11066 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11067 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11068 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11069 * \param [in] srcArrIndex index array of \b srcArr
11071 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11073 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11074 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11076 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11077 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11078 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11079 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11080 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11081 int *arrInOutPtr=arrInOut->getPointer();
11082 const int *srcArrPtr=srcArr->getConstPointer();
11083 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11085 if(*it>=0 && *it<nbOfTuples)
11087 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11088 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11091 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] !";
11092 throw INTERP_KERNEL::Exception(oss.str().c_str());
11097 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11098 throw INTERP_KERNEL::Exception(oss.str().c_str());
11104 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11105 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11106 * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11107 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11108 * A negative value in \b arrIn means that it is ignored.
11109 * 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.
11111 * \param [in] arrIn arr origin array from which the extraction will be done.
11112 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11113 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11114 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11116 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11118 int seed=0,nbOfDepthPeelingPerformed=0;
11119 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11123 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11124 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11125 * 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]].
11126 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11127 * A negative value in \b arrIn means that it is ignored.
11128 * 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.
11129 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11130 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11131 * \param [in] arrIn arr origin array from which the extraction will be done.
11132 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11133 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11134 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11135 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11136 * \sa MEDCouplingUMesh::partitionBySpreadZone
11138 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11140 nbOfDepthPeelingPerformed=0;
11142 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11143 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11146 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11150 std::vector<bool> fetched(nbOfTuples,false);
11151 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11154 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11156 nbOfDepthPeelingPerformed=0;
11157 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11158 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11159 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11160 std::vector<bool> fetched2(nbOfTuples,false);
11162 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11164 if(*seedElt>=0 && *seedElt<nbOfTuples)
11165 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11167 { 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()); }
11169 const int *arrInPtr=arrIn->getConstPointer();
11170 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11171 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11172 std::vector<int> idsToFetch1(seedBg,seedEnd);
11173 std::vector<int> idsToFetch2;
11174 std::vector<int> *idsToFetch=&idsToFetch1;
11175 std::vector<int> *idsToFetchOther=&idsToFetch2;
11176 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11178 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11179 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11181 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11182 std::swap(idsToFetch,idsToFetchOther);
11183 idsToFetchOther->clear();
11184 nbOfDepthPeelingPerformed++;
11186 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11189 int *retPtr=ret->getPointer();
11190 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11197 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11198 * 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
11199 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11200 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11202 * \param [in] start begin of set of ids of the input extraction (included)
11203 * \param [in] end end of set of ids of the input extraction (excluded)
11204 * \param [in] step step of the set of ids in range mode.
11205 * \param [in] arrIn arr origin array from which the extraction will be done.
11206 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11207 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11208 * \param [in] srcArrIndex index array of \b srcArr
11209 * \param [out] arrOut the resulting array
11210 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11212 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11214 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11215 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11216 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11218 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11219 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11222 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11224 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11225 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11226 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11228 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11230 if(it>=0 && it<nbOfTuples)
11231 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11234 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11235 throw INTERP_KERNEL::Exception(oss.str().c_str());
11238 srcArrIndexPtr=srcArrIndex->getConstPointer();
11239 arrIo->alloc(nbOfTuples+1,1);
11240 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11241 const int *arrInPtr=arrIn->getConstPointer();
11242 const int *srcArrPtr=srcArr->getConstPointer();
11243 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11244 int *arroPtr=arro->getPointer();
11245 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11247 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11250 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11251 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11255 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11256 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11259 arrOut=arro.retn();
11260 arrIndexOut=arrIo.retn();
11264 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11265 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11267 * \param [in] start begin of set of ids of the input extraction (included)
11268 * \param [in] end end of set of ids of the input extraction (excluded)
11269 * \param [in] step step of the set of ids in range mode.
11270 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11271 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11272 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11273 * \param [in] srcArrIndex index array of \b srcArr
11275 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11277 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11278 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11280 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11282 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11283 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11284 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11285 int *arrInOutPtr=arrInOut->getPointer();
11286 const int *srcArrPtr=srcArr->getConstPointer();
11287 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11289 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11291 if(it>=0 && it<nbOfTuples)
11293 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11294 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11297 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11298 throw INTERP_KERNEL::Exception(oss.str().c_str());
11303 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11304 throw INTERP_KERNEL::Exception(oss.str().c_str());
11310 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11311 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11312 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11313 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11314 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11316 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11318 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11320 checkFullyDefined();
11321 int mdim=getMeshDimension();
11322 int spaceDim=getSpaceDimension();
11324 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11325 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11326 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11327 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11328 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11329 ret->setCoords(getCoords());
11330 ret->allocateCells((int)partition.size());
11332 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11334 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11339 cell=tmp->buildUnionOf2DMesh();
11342 cell=tmp->buildUnionOf3DMesh();
11345 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11348 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11351 ret->finishInsertingCells();
11356 * This method partitions \b this into contiguous zone.
11357 * This method only needs a well defined connectivity. Coordinates are not considered here.
11358 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11360 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11362 int nbOfCellsCur=getNumberOfCells();
11363 std::vector<DataArrayInt *> ret;
11364 if(nbOfCellsCur<=0)
11366 DataArrayInt *neigh=0,*neighI=0;
11367 computeNeighborsOfCells(neigh,neighI);
11368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11369 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11370 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11372 while(seed<nbOfCellsCur)
11374 int nbOfPeelPerformed=0;
11375 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11376 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11378 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11379 ret.push_back((*it).retn());
11384 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11385 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11387 * \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.
11388 * \return a newly allocated DataArrayInt to be managed by the caller.
11389 * \throw In case of \a code has not the right format (typically of size 3*n)
11391 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11394 std::size_t nb=code.size()/3;
11395 if(code.size()%3!=0)
11396 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11397 ret->alloc((int)nb,2);
11398 int *retPtr=ret->getPointer();
11399 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11401 retPtr[0]=code[3*i+2];
11402 retPtr[1]=code[3*i+2]+code[3*i+1];
11408 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11409 * All cells in \a this are expected to be linear 3D cells.
11410 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11411 * It leads to an increase to number of cells.
11412 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11413 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11414 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11416 * \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.
11417 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11418 * \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.
11419 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11420 * an id of old cell producing it. The caller is to delete this array using
11421 * decrRef() as it is no more needed.
11422 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11424 * \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
11425 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11427 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11428 * \throw If \a this is not fully constituted with linear 3D cells.
11429 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11431 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11433 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11434 checkConnectivityFullyDefined();
11435 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11436 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11437 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11438 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11439 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11440 int *retPt(ret->getPointer());
11441 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11442 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11443 const int *oldc(_nodal_connec->begin());
11444 const int *oldci(_nodal_connec_index->begin());
11445 const double *coords(_coords->begin());
11446 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11448 std::vector<int> a; std::vector<double> b;
11449 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11450 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11451 const int *aa(&a[0]);
11454 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11456 *it=(-(*(it))-1+nbNodes);
11457 addPts->insertAtTheEnd(b.begin(),b.end());
11458 nbNodes+=(int)b.size()/3;
11460 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11461 newConn->insertAtTheEnd(aa,aa+4);
11463 if(!addPts->empty())
11465 addPts->rearrange(3);
11466 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11467 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11468 ret0->setCoords(addPts);
11472 nbOfAdditionalPoints=0;
11473 ret0->setCoords(getCoords());
11475 ret0->setNodalConnectivity(newConn);
11477 ret->computeOffsets2();
11478 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11479 return ret0.retn();
11483 * 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).
11485 * \sa MEDCouplingUMesh::split2DCells
11487 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11489 checkConnectivityFullyDefined();
11490 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11491 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11492 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11493 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11494 int prevPosOfCi(ciPtr[0]);
11495 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11497 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11498 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11499 for(int j=0;j<sz;j++)
11501 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11502 for(int k=0;k<sz2;k++)
11503 *cPtr++=subPtr[offset2+k];
11505 *cPtr++=oldConn[prevPosOfCi+j+2];
11508 prevPosOfCi=ciPtr[1];
11509 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11512 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11513 _nodal_connec->decrRef();
11514 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11517 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11523 int ret(nodesCnter++);
11525 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11526 addCoo.insertAtTheEnd(newPt,newPt+2);
11531 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11537 int ret(nodesCnter++);
11539 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11540 addCoo.insertAtTheEnd(newPt,newPt+2);
11548 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)
11551 int trueStart(start>=0?start:nbOfEdges+start);
11552 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11553 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11558 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11559 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11560 middles.push_back(tmp3+offset);
11563 middles.push_back(connBg[trueStart+nbOfEdges]);
11567 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)
11569 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11570 newConnOfCell->pushBackSilent(tmpEnd);
11575 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11576 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11577 middles.push_back(tmp3+offset);
11580 middles.push_back(connBg[start+nbOfEdges]);
11584 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)
11586 // only the quadratic point to deal with:
11591 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11592 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11593 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11594 middles.push_back(tmp3+offset);
11597 middles.push_back(connBg[start+nbOfEdges]);
11604 * 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 ) .
11605 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11607 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11609 std::size_t sz(std::distance(connBg,connEnd));
11610 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11611 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11613 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11614 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11615 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11616 unsigned nbOfHit(0); // number of fusions operated
11617 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11618 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
11619 INTERP_KERNEL::NormalizedCellType typeOfSon;
11620 std::vector<int> middles;
11622 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11624 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11625 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11626 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11627 posEndElt = posBaseElt+1;
11629 // Look backward first: are the final edges of the cells colinear with the first ones?
11630 // This initializes posBaseElt.
11633 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11635 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11636 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11637 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11638 bool isColinear=eint->areColinears();
11651 // Now move forward:
11652 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11653 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11655 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11656 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11657 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11658 bool isColinear(eint->areColinears());
11670 //push [posBaseElt,posEndElt) in newConnOfCell using e
11671 // 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!
11673 // at the begining of the connectivity (insert type)
11674 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11675 else if((nbOfHit+nbOfTurn) != (nbs-1))
11677 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11678 if ((nbOfHit+nbOfTurn) == (nbs-1))
11679 // at the end (only quad points to deal with)
11680 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11681 posBaseElt=posEndElt;
11684 if(!middles.empty())
11685 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11690 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11692 * \return int - the number of new nodes created.
11693 * \sa MEDCouplingUMesh::split2DCells
11695 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11698 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11700 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11701 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11702 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11703 const double *oldCoordsPtr(getCoords()->begin());
11704 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11705 int prevPosOfCi(ciPtr[0]);
11706 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11708 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11709 for(int j=0;j<sz;j++)
11710 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11711 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11712 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11714 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11718 cPtr[1]=oldConn[prevPosOfCi+2+j];
11719 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11722 std::vector<INTERP_KERNEL::Node *> ns(3);
11723 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11724 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11725 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11726 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11727 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11729 cPtr[1]=subPtr[offset2+k];
11730 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11732 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11734 { cPtr[1]=tmpEnd; }
11735 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11737 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11738 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11742 _nodal_connec->decrRef();
11743 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11744 addCoo->rearrange(2);
11745 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11747 return addCoo->getNumberOfTuples();
11750 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11752 if(nodalConnec && nodalConnecIndex)
11755 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11756 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11758 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11759 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11763 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11764 _own_cell(true),_cell_id(-1),_nb_cell(0)
11769 _nb_cell=mesh->getNumberOfCells();
11773 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11781 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11782 _own_cell(false),_cell_id(bg-1),
11789 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11792 if(_cell_id<_nb_cell)
11801 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11807 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11809 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11812 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11818 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11826 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11832 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11837 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11842 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11844 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11847 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11852 _nb_cell=mesh->getNumberOfCells();
11856 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11863 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11865 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11866 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11867 if(_cell_id<_nb_cell)
11869 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11870 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11871 int startId=_cell_id;
11872 _cell_id+=nbOfElems;
11873 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11879 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11883 _conn=mesh->getNodalConnectivity()->getPointer();
11884 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11888 void MEDCouplingUMeshCell::next()
11890 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11895 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11898 std::string MEDCouplingUMeshCell::repr() const
11900 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11902 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11904 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11908 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11911 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11913 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11914 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11916 return INTERP_KERNEL::NORM_ERROR;
11919 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11922 if(_conn_lgth!=NOTICABLE_FIRST_VAL)