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 MEDCouplingPointSet *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 MEDCouplingPointSet *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 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2037 if(getMeshDimension()!=-1)
2038 return 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 MEDCouplingPointSet * - 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 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2076 if(getMeshDimension()!=-1)
2077 return 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 MEDCouplingPointSet * - 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 MEDCouplingPointSet *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 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 MEDCouplingPointSet * - 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 MEDCouplingPointSet *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 MEDCouplingPointSet *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 MEDCouplingPointSet *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 MEDCouplingPointSet *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. \b 0 for translation (most simple),
4673 * \b 1 for translation and rotation around point of 'mesh1D'.
4674 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4676 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4678 checkFullyDefined();
4679 mesh1D->checkFullyDefined();
4680 if(!mesh1D->isContiguous1D())
4681 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4682 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4683 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4684 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4685 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4686 if(mesh1D->getMeshDimension()!=1)
4687 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4689 if(isPresenceOfQuadratic())
4691 if(mesh1D->isFullyQuadratic())
4694 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4696 int oldNbOfNodes(getNumberOfNodes());
4697 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4702 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4707 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4711 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4713 setCoords(newCoords);
4714 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4720 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4721 * If it is not the case an exception will be thrown.
4722 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4723 * intersection of plane defined by ('origin','vec').
4724 * This method has one in/out parameter : 'cut3DCurve'.
4725 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4726 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4727 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4728 * This method will throw an exception if \a this contains a non linear segment.
4730 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4732 checkFullyDefined();
4733 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4734 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4735 int ncells=getNumberOfCells();
4736 int nnodes=getNumberOfNodes();
4737 double vec2[3],vec3[3],vec4[3];
4738 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4740 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4741 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4742 const int *conn=_nodal_connec->getConstPointer();
4743 const int *connI=_nodal_connec_index->getConstPointer();
4744 const double *coo=_coords->getConstPointer();
4745 std::vector<double> addCoo;
4746 for(int i=0;i<ncells;i++)
4748 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4750 if(cut3DCurve[i]==-2)
4752 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4753 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];
4754 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4755 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4756 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4758 const double *st2=coo+3*st;
4759 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4760 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]));
4761 if(pos>eps && pos<1-eps)
4763 int nNode=((int)addCoo.size())/3;
4764 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4765 addCoo.insert(addCoo.end(),vec4,vec4+3);
4766 cut3DCurve[i]=nnodes+nNode;
4772 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4776 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4777 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4778 coo2->alloc(newNbOfNodes,3);
4779 double *tmp=coo2->getPointer();
4780 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4781 std::copy(addCoo.begin(),addCoo.end(),tmp);
4782 DataArrayDouble::SetArrayIn(coo2,_coords);
4787 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4788 * \param mesh1D is the input 1D mesh used for translation computation.
4789 * \return newCoords new coords filled by this method.
4791 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4793 int oldNbOfNodes=getNumberOfNodes();
4794 int nbOf1DCells=mesh1D->getNumberOfCells();
4795 int spaceDim=getSpaceDimension();
4796 DataArrayDouble *ret=DataArrayDouble::New();
4797 std::vector<bool> isQuads;
4798 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4799 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4800 double *retPtr=ret->getPointer();
4801 const double *coords=getCoords()->getConstPointer();
4802 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4804 std::vector<double> c;
4808 for(int i=0;i<nbOf1DCells;i++)
4811 mesh1D->getNodeIdsOfCell(i,v);
4813 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4814 mesh1D->getCoordinatesOfNode(v[0],c);
4815 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4816 for(int j=0;j<oldNbOfNodes;j++)
4817 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4821 mesh1D->getCoordinatesOfNode(v[1],c);
4822 mesh1D->getCoordinatesOfNode(v[0],c);
4823 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4824 for(int j=0;j<oldNbOfNodes;j++)
4825 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4828 ret->copyStringInfoFrom(*getCoords());
4833 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4834 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4835 * \return newCoords new coords filled by this method.
4837 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4839 if(mesh1D->getSpaceDimension()==2)
4840 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4841 if(mesh1D->getSpaceDimension()==3)
4842 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4843 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4847 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4848 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4849 * \return newCoords new coords filled by this method.
4851 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4854 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4855 int oldNbOfNodes=getNumberOfNodes();
4856 int nbOf1DCells=mesh1D->getNumberOfCells();
4858 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4859 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4860 int nbOfLevsInVec=nbOf1DCells+1;
4861 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4862 double *retPtr=ret->getPointer();
4863 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4864 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4865 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4866 tmp->setCoords(tmp2);
4867 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4868 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4869 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4870 for(int i=1;i<nbOfLevsInVec;i++)
4872 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4873 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4874 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4875 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4876 tmp->translate(vec);
4877 double tmp3[2],radius,alpha,alpha0;
4878 const double *p0=i+1<nbOfLevsInVec?begin:third;
4879 const double *p1=i+1<nbOfLevsInVec?end:begin;
4880 const double *p2=i+1<nbOfLevsInVec?third:end;
4881 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4882 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]);
4883 double angle=acos(cosangle/(radius*radius));
4884 tmp->rotate(end,0,angle);
4885 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4891 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4892 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4893 * \return newCoords new coords filled by this method.
4895 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4898 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4899 int oldNbOfNodes=getNumberOfNodes();
4900 int nbOf1DCells=mesh1D->getNumberOfCells();
4902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4903 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4904 int nbOfLevsInVec=nbOf1DCells+1;
4905 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4906 double *retPtr=ret->getPointer();
4907 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4908 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4909 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4910 tmp->setCoords(tmp2);
4911 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4912 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4913 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4914 for(int i=1;i<nbOfLevsInVec;i++)
4916 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4917 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4918 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4919 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4920 tmp->translate(vec);
4921 double tmp3[2],radius,alpha,alpha0;
4922 const double *p0=i+1<nbOfLevsInVec?begin:third;
4923 const double *p1=i+1<nbOfLevsInVec?end:begin;
4924 const double *p2=i+1<nbOfLevsInVec?third:end;
4925 double vecPlane[3]={
4926 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4927 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4928 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4930 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4933 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4934 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4935 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4937 double c2=cos(asin(s2));
4939 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4940 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4941 {-vec2[1]*s2, vec2[0]*s2, c2}
4943 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]};
4944 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]};
4945 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]};
4946 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4947 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]);
4948 double angle=acos(cosangle/(radius*radius));
4949 tmp->rotate(end,vecPlane,angle);
4951 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4957 * This method is private because not easy to use for end user. This method is const contrary to
4958 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4959 * the coords sorted slice by slice.
4960 * \param isQuad specifies presence of quadratic cells.
4962 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4964 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4965 int nbOf2DCells(getNumberOfCells());
4966 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4967 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4968 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4970 newConnI->alloc(nbOf3DCells+1,1);
4971 int *newConnIPtr(newConnI->getPointer());
4973 std::vector<int> newc;
4974 for(int j=0;j<nbOf2DCells;j++)
4976 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4977 *newConnIPtr++=(int)newc.size();
4979 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4980 int *newConnPtr(newConn->getPointer());
4981 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4982 newConnIPtr=newConnI->getPointer();
4983 for(int iz=0;iz<nbOf1DCells;iz++)
4986 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4987 const int *posOfTypeOfCell(newConnIPtr);
4988 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4990 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4991 if(icell!=*posOfTypeOfCell)
4994 *newConnPtr=(*iter)+iz*deltaPerLev;
5005 ret->setConnectivity(newConn,newConnI,true);
5006 ret->setCoords(getCoords());
5011 * Checks if \a this mesh is constituted by only quadratic cells.
5012 * \return bool - \c true if there are only quadratic cells in \a this mesh.
5013 * \throw If the coordinates array is not set.
5014 * \throw If the nodal connectivity of cells is not defined.
5016 bool MEDCouplingUMesh::isFullyQuadratic() const
5018 checkFullyDefined();
5020 int nbOfCells=getNumberOfCells();
5021 for(int i=0;i<nbOfCells && ret;i++)
5023 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5024 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5025 ret=cm.isQuadratic();
5031 * Checks if \a this mesh includes any quadratic cell.
5032 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5033 * \throw If the coordinates array is not set.
5034 * \throw If the nodal connectivity of cells is not defined.
5036 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5038 checkFullyDefined();
5040 int nbOfCells=getNumberOfCells();
5041 for(int i=0;i<nbOfCells && !ret;i++)
5043 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5044 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5045 ret=cm.isQuadratic();
5051 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5052 * this mesh, it remains unchanged.
5053 * \throw If the coordinates array is not set.
5054 * \throw If the nodal connectivity of cells is not defined.
5056 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5058 checkFullyDefined();
5059 int nbOfCells=getNumberOfCells();
5061 const int *iciptr=_nodal_connec_index->getConstPointer();
5062 for(int i=0;i<nbOfCells;i++)
5064 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5065 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5066 if(cm.isQuadratic())
5068 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5069 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5070 if(!cml.isDynamic())
5071 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5073 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5078 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5080 const int *icptr=_nodal_connec->getConstPointer();
5081 newConn->alloc(getMeshLength()-delta,1);
5082 newConnI->alloc(nbOfCells+1,1);
5083 int *ocptr=newConn->getPointer();
5084 int *ociptr=newConnI->getPointer();
5087 for(int i=0;i<nbOfCells;i++,ociptr++)
5089 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5090 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5091 if(!cm.isQuadratic())
5093 _types.insert(type);
5094 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5095 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5099 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5100 _types.insert(typel);
5101 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5102 int newNbOfNodes=cml.getNumberOfNodes();
5104 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5105 *ocptr++=(int)typel;
5106 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5107 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5110 setConnectivity(newConn,newConnI,false);
5114 * This method converts all linear cell in \a this to quadratic one.
5115 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5116 * 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)
5117 * 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.
5118 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5119 * end of the existing coordinates.
5121 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5122 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5123 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5125 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5127 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5129 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5131 DataArrayInt *conn=0,*connI=0;
5132 DataArrayDouble *coords=0;
5133 std::set<INTERP_KERNEL::NormalizedCellType> types;
5134 checkFullyDefined();
5135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5136 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5137 int meshDim=getMeshDimension();
5138 switch(conversionType)
5144 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5145 connSafe=conn; connISafe=connI; coordsSafe=coords;
5148 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5149 connSafe=conn; connISafe=connI; coordsSafe=coords;
5152 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5153 connSafe=conn; connISafe=connI; coordsSafe=coords;
5156 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5164 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5165 connSafe=conn; connISafe=connI; coordsSafe=coords;
5168 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5169 connSafe=conn; connISafe=connI; coordsSafe=coords;
5172 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5173 connSafe=conn; connISafe=connI; coordsSafe=coords;
5176 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5183 setConnectivity(connSafe,connISafe,false);
5185 setCoords(coordsSafe);
5191 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5192 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5193 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5194 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5195 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5196 * This method can be seen as the opposite method of colinearize2D.
5197 * 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
5198 * to avoid to modify the numbering of existing nodes.
5200 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5201 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5202 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5203 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5204 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5205 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5206 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5208 * \sa buildDescendingConnectivity2
5210 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5211 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5213 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5214 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5215 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5216 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5218 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5219 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5220 //DataArrayInt *out0(0),*outi0(0);
5221 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5222 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5223 //out0s=out0s->buildUnique(); out0s->sort(true);
5228 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5229 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5230 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5232 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5234 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5238 int nbOfCells=getNumberOfCells();
5239 int nbOfNodes=getNumberOfNodes();
5240 const int *cPtr=_nodal_connec->getConstPointer();
5241 const int *icPtr=_nodal_connec_index->getConstPointer();
5242 int lastVal=0,offset=nbOfNodes;
5243 for(int i=0;i<nbOfCells;i++,icPtr++)
5245 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5246 if(type==INTERP_KERNEL::NORM_SEG2)
5248 types.insert(INTERP_KERNEL::NORM_SEG3);
5249 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5250 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5251 newConn->pushBackSilent(offset++);
5253 newConnI->pushBackSilent(lastVal);
5254 ret->pushBackSilent(i);
5259 lastVal+=(icPtr[1]-icPtr[0]);
5260 newConnI->pushBackSilent(lastVal);
5261 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5264 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5265 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5269 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
5271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5275 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5276 DataArrayInt *conn1D=0,*conn1DI=0;
5277 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5278 DataArrayDouble *coordsTmp=0;
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5282 const int *c1DPtr=conn1D->begin();
5283 const int *c1DIPtr=conn1DI->begin();
5284 int nbOfCells=getNumberOfCells();
5285 const int *cPtr=_nodal_connec->getConstPointer();
5286 const int *icPtr=_nodal_connec_index->getConstPointer();
5288 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5290 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5291 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5292 if(!cm.isQuadratic())
5294 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5295 types.insert(typ2); newConn->pushBackSilent(typ2);
5296 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5297 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5298 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5299 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5300 newConnI->pushBackSilent(lastVal);
5301 ret->pushBackSilent(i);
5306 lastVal+=(icPtr[1]-icPtr[0]);
5307 newConnI->pushBackSilent(lastVal);
5308 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5311 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5316 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5317 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5318 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5320 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5324 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5327 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5330 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5337 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5338 DataArrayInt *conn1D=0,*conn1DI=0;
5339 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5340 DataArrayDouble *coordsTmp=0;
5341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5342 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5344 const int *c1DPtr=conn1D->begin();
5345 const int *c1DIPtr=conn1DI->begin();
5346 int nbOfCells=getNumberOfCells();
5347 const int *cPtr=_nodal_connec->getConstPointer();
5348 const int *icPtr=_nodal_connec_index->getConstPointer();
5349 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5350 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5352 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5353 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5354 if(!cm.isQuadratic())
5356 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5357 types.insert(typ2); newConn->pushBackSilent(typ2);
5358 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5359 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5360 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5361 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5362 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5363 newConnI->pushBackSilent(lastVal);
5364 ret->pushBackSilent(i);
5369 lastVal+=(icPtr[1]-icPtr[0]);
5370 newConnI->pushBackSilent(lastVal);
5371 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5374 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5375 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5380 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5381 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5382 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5384 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5387 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5388 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5391 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5394 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5402 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5403 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5404 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5405 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5406 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5409 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5410 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5411 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5413 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5414 int nbOfCells=getNumberOfCells();
5415 const int *cPtr=_nodal_connec->getConstPointer();
5416 const int *icPtr=_nodal_connec_index->getConstPointer();
5417 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5418 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5420 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5421 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5422 if(!cm.isQuadratic())
5424 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5425 if(typ2==INTERP_KERNEL::NORM_ERROR)
5427 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5428 throw INTERP_KERNEL::Exception(oss.str().c_str());
5430 types.insert(typ2); newConn->pushBackSilent(typ2);
5431 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5432 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5433 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5434 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5436 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5437 int tmpPos=newConn->getNumberOfTuples();
5438 newConn->pushBackSilent(nodeId2);
5439 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5441 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5442 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5443 newConnI->pushBackSilent(lastVal);
5444 ret->pushBackSilent(i);
5449 lastVal+=(icPtr[1]-icPtr[0]);
5450 newConnI->pushBackSilent(lastVal);
5451 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5456 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5457 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5458 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5459 int *c=newConn->getPointer();
5460 const int *cI(newConnI->begin());
5461 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5462 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5463 offset=coordsTmp2Safe->getNumberOfTuples();
5464 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5465 c[cI[(*elt)+1]-1]+=offset;
5466 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5471 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5472 * so that the number of cells remains the same. Quadratic faces are converted to
5473 * polygons. This method works only for 2D meshes in
5474 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5475 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5476 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5477 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5478 * a polylinized edge constituting the input polygon.
5479 * \throw If the coordinates array is not set.
5480 * \throw If the nodal connectivity of cells is not defined.
5481 * \throw If \a this->getMeshDimension() != 2.
5482 * \throw If \a this->getSpaceDimension() != 2.
5484 void MEDCouplingUMesh::tessellate2D(double eps)
5486 checkFullyDefined();
5487 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5488 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5489 double epsa=fabs(eps);
5490 if(epsa<std::numeric_limits<double>::min())
5491 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 !");
5492 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5493 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5494 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5495 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5496 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5497 revDesc1=0; revDescIndx1=0;
5498 mDesc->tessellate2DCurve(eps);
5499 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5500 setCoords(mDesc->getCoords());
5504 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5505 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5506 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5507 * a sub-divided edge.
5508 * \throw If the coordinates array is not set.
5509 * \throw If the nodal connectivity of cells is not defined.
5510 * \throw If \a this->getMeshDimension() != 1.
5511 * \throw If \a this->getSpaceDimension() != 2.
5513 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5515 checkFullyDefined();
5516 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5518 double epsa=fabs(eps);
5519 if(epsa<std::numeric_limits<double>::min())
5520 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 !");
5521 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5522 int nbCells=getNumberOfCells();
5523 int nbNodes=getNumberOfNodes();
5524 const int *conn=_nodal_connec->getConstPointer();
5525 const int *connI=_nodal_connec_index->getConstPointer();
5526 const double *coords=_coords->getConstPointer();
5527 std::vector<double> addCoo;
5528 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5529 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5530 newConnI->alloc(nbCells+1,1);
5531 int *newConnIPtr=newConnI->getPointer();
5534 INTERP_KERNEL::Node *tmp2[3];
5535 std::set<INTERP_KERNEL::NormalizedCellType> types;
5536 for(int i=0;i<nbCells;i++,newConnIPtr++)
5538 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5539 if(cm.isQuadratic())
5540 {//assert(connI[i+1]-connI[i]-1==3)
5541 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5542 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5543 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5544 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5545 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5548 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5549 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5551 newConnIPtr[1]=(int)newConn.size();
5555 types.insert(INTERP_KERNEL::NORM_SEG2);
5556 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5557 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5558 newConnIPtr[1]=newConnIPtr[0]+3;
5563 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5564 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5565 newConnIPtr[1]=newConnIPtr[0]+3;
5568 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5571 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5572 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5573 newConnArr->alloc((int)newConn.size(),1);
5574 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5575 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5576 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5577 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5578 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5579 std::copy(addCoo.begin(),addCoo.end(),work);
5580 DataArrayDouble::SetArrayIn(newCoords,_coords);
5585 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5586 * In addition, returns an array mapping new cells to old ones. <br>
5587 * This method typically increases the number of cells in \a this mesh
5588 * but the number of nodes remains \b unchanged.
5589 * That's why the 3D splitting policies
5590 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5591 * \param [in] policy - specifies a pattern used for splitting.
5592 * The semantic of \a policy is:
5593 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5594 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5595 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5596 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5599 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5600 * an id of old cell producing it. The caller is to delete this array using
5601 * decrRef() as it is no more needed.
5603 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5604 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5605 * and \a this->getMeshDimension() != 3.
5606 * \throw If \a policy is not one of the four discussed above.
5607 * \throw If the nodal connectivity of cells is not defined.
5608 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5610 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5615 return simplexizePol0();
5617 return simplexizePol1();
5618 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5619 return simplexizePlanarFace5();
5620 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5621 return simplexizePlanarFace6();
5623 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)");
5628 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5629 * - 1D: INTERP_KERNEL::NORM_SEG2
5630 * - 2D: INTERP_KERNEL::NORM_TRI3
5631 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5633 * This method is useful for users that need to use P1 field services as
5634 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5635 * All these methods need mesh support containing only simplex cells.
5636 * \return bool - \c true if there are only simplex cells in \a this mesh.
5637 * \throw If the coordinates array is not set.
5638 * \throw If the nodal connectivity of cells is not defined.
5639 * \throw If \a this->getMeshDimension() < 1.
5641 bool MEDCouplingUMesh::areOnlySimplexCells() const
5643 checkFullyDefined();
5644 int mdim=getMeshDimension();
5645 if(mdim<1 || mdim>3)
5646 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5647 int nbCells=getNumberOfCells();
5648 const int *conn=_nodal_connec->getConstPointer();
5649 const int *connI=_nodal_connec_index->getConstPointer();
5650 for(int i=0;i<nbCells;i++)
5652 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5660 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5662 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5664 checkConnectivityFullyDefined();
5665 if(getMeshDimension()!=2)
5666 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5667 int nbOfCells=getNumberOfCells();
5668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5669 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5670 ret->alloc(nbOfCells+nbOfCutCells,1);
5671 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5672 int *retPt=ret->getPointer();
5673 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5674 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5675 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5676 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5677 int *pt=newConn->getPointer();
5678 int *ptI=newConnI->getPointer();
5680 const int *oldc=_nodal_connec->getConstPointer();
5681 const int *ci=_nodal_connec_index->getConstPointer();
5682 for(int i=0;i<nbOfCells;i++,ci++)
5684 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5686 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5687 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5688 pt=std::copy(tmp,tmp+8,pt);
5697 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5698 ptI[1]=ptI[0]+ci[1]-ci[0];
5703 _nodal_connec->decrRef();
5704 _nodal_connec=newConn.retn();
5705 _nodal_connec_index->decrRef();
5706 _nodal_connec_index=newConnI.retn();
5713 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5715 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5717 checkConnectivityFullyDefined();
5718 if(getMeshDimension()!=2)
5719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5720 int nbOfCells=getNumberOfCells();
5721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5722 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5723 ret->alloc(nbOfCells+nbOfCutCells,1);
5724 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5725 int *retPt=ret->getPointer();
5726 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5727 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5728 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5729 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5730 int *pt=newConn->getPointer();
5731 int *ptI=newConnI->getPointer();
5733 const int *oldc=_nodal_connec->getConstPointer();
5734 const int *ci=_nodal_connec_index->getConstPointer();
5735 for(int i=0;i<nbOfCells;i++,ci++)
5737 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5739 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5740 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5741 pt=std::copy(tmp,tmp+8,pt);
5750 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5751 ptI[1]=ptI[0]+ci[1]-ci[0];
5756 _nodal_connec->decrRef();
5757 _nodal_connec=newConn.retn();
5758 _nodal_connec_index->decrRef();
5759 _nodal_connec_index=newConnI.retn();
5766 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5768 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5770 checkConnectivityFullyDefined();
5771 if(getMeshDimension()!=3)
5772 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5773 int nbOfCells=getNumberOfCells();
5774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5775 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5776 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5777 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5778 int *retPt=ret->getPointer();
5779 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5780 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5781 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5782 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5783 int *pt=newConn->getPointer();
5784 int *ptI=newConnI->getPointer();
5786 const int *oldc=_nodal_connec->getConstPointer();
5787 const int *ci=_nodal_connec_index->getConstPointer();
5788 for(int i=0;i<nbOfCells;i++,ci++)
5790 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5792 for(int j=0;j<5;j++,pt+=5,ptI++)
5794 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5795 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];
5802 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5803 ptI[1]=ptI[0]+ci[1]-ci[0];
5808 _nodal_connec->decrRef();
5809 _nodal_connec=newConn.retn();
5810 _nodal_connec_index->decrRef();
5811 _nodal_connec_index=newConnI.retn();
5818 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5820 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5822 checkConnectivityFullyDefined();
5823 if(getMeshDimension()!=3)
5824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5825 int nbOfCells=getNumberOfCells();
5826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5827 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5828 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5829 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5830 int *retPt=ret->getPointer();
5831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5833 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5834 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5835 int *pt=newConn->getPointer();
5836 int *ptI=newConnI->getPointer();
5838 const int *oldc=_nodal_connec->getConstPointer();
5839 const int *ci=_nodal_connec_index->getConstPointer();
5840 for(int i=0;i<nbOfCells;i++,ci++)
5842 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5844 for(int j=0;j<6;j++,pt+=5,ptI++)
5846 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5847 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];
5854 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5855 ptI[1]=ptI[0]+ci[1]-ci[0];
5860 _nodal_connec->decrRef();
5861 _nodal_connec=newConn.retn();
5862 _nodal_connec_index->decrRef();
5863 _nodal_connec_index=newConnI.retn();
5870 * 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.
5871 * This method completly ignore coordinates.
5872 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5873 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5874 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5875 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5877 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5879 checkFullyDefined();
5880 if(getMeshDimension()!=2)
5881 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5882 int nbOfCells=getNumberOfCells();
5883 int *connI=_nodal_connec_index->getPointer();
5885 for(int i=0;i<nbOfCells;i++,connI++)
5887 int offset=descIndex[i];
5888 int nbOfEdges=descIndex[i+1]-offset;
5890 bool ddirect=desc[offset+nbOfEdges-1]>0;
5891 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5892 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5893 for(int j=0;j<nbOfEdges;j++)
5895 bool direct=desc[offset+j]>0;
5896 int edgeId=std::abs(desc[offset+j])-1;
5897 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5899 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5900 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5901 int ref2=direct?id1:id2;
5904 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5905 newConnLgth+=nbOfSubNodes-1;
5910 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5911 throw INTERP_KERNEL::Exception(oss.str().c_str());
5916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5919 newConnLgth++;//+1 is for cell type
5920 connI[1]=newConnLgth;
5923 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5924 newConn->alloc(newConnLgth,1);
5925 int *work=newConn->getPointer();
5926 for(int i=0;i<nbOfCells;i++)
5928 *work++=INTERP_KERNEL::NORM_POLYGON;
5929 int offset=descIndex[i];
5930 int nbOfEdges=descIndex[i+1]-offset;
5931 for(int j=0;j<nbOfEdges;j++)
5933 bool direct=desc[offset+j]>0;
5934 int edgeId=std::abs(desc[offset+j])-1;
5936 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5939 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5940 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5941 work=std::copy(it,it+nbOfSubNodes-1,work);
5945 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5948 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5952 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5953 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5954 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5955 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5956 * so it can be useful to call mergeNodes() before calling this method.
5957 * \throw If \a this->getMeshDimension() <= 1.
5958 * \throw If the coordinates array is not set.
5959 * \throw If the nodal connectivity of cells is not defined.
5961 void MEDCouplingUMesh::convertDegeneratedCells()
5963 checkFullyDefined();
5964 if(getMeshDimension()<=1)
5965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5966 int nbOfCells=getNumberOfCells();
5969 int initMeshLgth=getMeshLength();
5970 int *conn=_nodal_connec->getPointer();
5971 int *index=_nodal_connec_index->getPointer();
5975 for(int i=0;i<nbOfCells;i++)
5977 lgthOfCurCell=index[i+1]-posOfCurCell;
5978 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5980 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5981 conn+newPos+1,newLgth);
5982 conn[newPos]=newType;
5984 posOfCurCell=index[i+1];
5987 if(newPos!=initMeshLgth)
5988 _nodal_connec->reAlloc(newPos);
5993 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5994 * A cell is considered to be oriented correctly if an angle between its
5995 * normal vector and a given vector is less than \c PI / \c 2.
5996 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5998 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6000 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6001 * is not cleared before filling in.
6002 * \throw If \a this->getMeshDimension() != 2.
6003 * \throw If \a this->getSpaceDimension() != 3.
6005 * \if ENABLE_EXAMPLES
6006 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6007 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6010 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6012 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6013 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6014 int nbOfCells=getNumberOfCells();
6015 const int *conn=_nodal_connec->getConstPointer();
6016 const int *connI=_nodal_connec_index->getConstPointer();
6017 const double *coordsPtr=_coords->getConstPointer();
6018 for(int i=0;i<nbOfCells;i++)
6020 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6021 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6023 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6024 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6031 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6032 * considered to be oriented correctly if an angle between its normal vector and a
6033 * given vector is less than \c PI / \c 2.
6034 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6036 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6038 * \throw If \a this->getMeshDimension() != 2.
6039 * \throw If \a this->getSpaceDimension() != 3.
6041 * \if ENABLE_EXAMPLES
6042 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6043 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6046 * \sa changeOrientationOfCells
6048 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6050 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6051 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6052 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6053 const int *connI(_nodal_connec_index->getConstPointer());
6054 const double *coordsPtr(_coords->getConstPointer());
6055 bool isModified(false);
6056 for(int i=0;i<nbOfCells;i++)
6058 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6059 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6061 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6062 bool isQuadratic(cm.isQuadratic());
6063 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6066 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6071 _nodal_connec->declareAsNew();
6076 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6078 * \sa orientCorrectly2DCells
6080 void MEDCouplingUMesh::changeOrientationOfCells()
6082 int mdim(getMeshDimension());
6083 if(mdim!=2 && mdim!=1)
6084 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6085 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6086 const int *connI(_nodal_connec_index->getConstPointer());
6089 for(int i=0;i<nbOfCells;i++)
6091 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6092 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6093 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6098 for(int i=0;i<nbOfCells;i++)
6100 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6101 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6102 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6108 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6109 * oriented facets. The normal vector of the facet should point out of the cell.
6110 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6111 * is not cleared before filling in.
6112 * \throw If \a this->getMeshDimension() != 3.
6113 * \throw If \a this->getSpaceDimension() != 3.
6114 * \throw If the coordinates array is not set.
6115 * \throw If the nodal connectivity of cells is not defined.
6117 * \if ENABLE_EXAMPLES
6118 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6119 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6122 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6124 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6125 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6126 int nbOfCells=getNumberOfCells();
6127 const int *conn=_nodal_connec->getConstPointer();
6128 const int *connI=_nodal_connec_index->getConstPointer();
6129 const double *coordsPtr=_coords->getConstPointer();
6130 for(int i=0;i<nbOfCells;i++)
6132 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6133 if(type==INTERP_KERNEL::NORM_POLYHED)
6135 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6142 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6144 * \throw If \a this->getMeshDimension() != 3.
6145 * \throw If \a this->getSpaceDimension() != 3.
6146 * \throw If the coordinates array is not set.
6147 * \throw If the nodal connectivity of cells is not defined.
6148 * \throw If the reparation fails.
6150 * \if ENABLE_EXAMPLES
6151 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6152 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6154 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6156 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6158 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6159 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6160 int nbOfCells=getNumberOfCells();
6161 int *conn=_nodal_connec->getPointer();
6162 const int *connI=_nodal_connec_index->getConstPointer();
6163 const double *coordsPtr=_coords->getConstPointer();
6164 for(int i=0;i<nbOfCells;i++)
6166 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6167 if(type==INTERP_KERNEL::NORM_POLYHED)
6171 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6172 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6174 catch(INTERP_KERNEL::Exception& e)
6176 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6177 throw INTERP_KERNEL::Exception(oss.str().c_str());
6185 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6186 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6187 * according to which the first facet of the cell should be oriented to have the normal vector
6188 * pointing out of cell.
6189 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6190 * cells. The caller is to delete this array using decrRef() as it is no more
6192 * \throw If \a this->getMeshDimension() != 3.
6193 * \throw If \a this->getSpaceDimension() != 3.
6194 * \throw If the coordinates array is not set.
6195 * \throw If the nodal connectivity of cells is not defined.
6197 * \if ENABLE_EXAMPLES
6198 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6199 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6201 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6203 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6205 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6206 if(getMeshDimension()!=3)
6207 throw INTERP_KERNEL::Exception(msg);
6208 int spaceDim=getSpaceDimension();
6210 throw INTERP_KERNEL::Exception(msg);
6212 int nbOfCells=getNumberOfCells();
6213 int *conn=_nodal_connec->getPointer();
6214 const int *connI=_nodal_connec_index->getConstPointer();
6215 const double *coo=getCoords()->getConstPointer();
6216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6217 for(int i=0;i<nbOfCells;i++)
6219 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6220 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6222 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6224 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6225 cells->pushBackSilent(i);
6229 return cells.retn();
6233 * This method is a faster method to correct orientation of all 3D cells in \a this.
6234 * 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.
6235 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6237 * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6238 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6240 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6242 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6243 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6244 int nbOfCells=getNumberOfCells();
6245 int *conn=_nodal_connec->getPointer();
6246 const int *connI=_nodal_connec_index->getConstPointer();
6247 const double *coordsPtr=_coords->getConstPointer();
6248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6249 for(int i=0;i<nbOfCells;i++)
6251 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6254 case INTERP_KERNEL::NORM_TETRA4:
6256 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6258 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6259 ret->pushBackSilent(i);
6263 case INTERP_KERNEL::NORM_PYRA5:
6265 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6267 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6268 ret->pushBackSilent(i);
6272 case INTERP_KERNEL::NORM_PENTA6:
6273 case INTERP_KERNEL::NORM_HEXA8:
6274 case INTERP_KERNEL::NORM_HEXGP12:
6276 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6278 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6279 ret->pushBackSilent(i);
6283 case INTERP_KERNEL::NORM_POLYHED:
6285 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6287 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6288 ret->pushBackSilent(i);
6293 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 !");
6301 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6302 * If it is not the case an exception will be thrown.
6303 * This method is fast because the first cell of \a this is used to compute the plane.
6304 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6305 * \param pos output of size at least 3 used to store a point owned of searched plane.
6307 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6309 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6310 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6311 const int *conn=_nodal_connec->getConstPointer();
6312 const int *connI=_nodal_connec_index->getConstPointer();
6313 const double *coordsPtr=_coords->getConstPointer();
6314 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6315 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6319 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6320 * cells. Currently cells of the following types are treated:
6321 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6322 * For a cell of other type an exception is thrown.
6323 * Space dimension of a 2D mesh can be either 2 or 3.
6324 * The Edge Ratio of a cell \f$t\f$ is:
6325 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6326 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6327 * the smallest edge lengths of \f$t\f$.
6328 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6329 * cells and one time, lying on \a this mesh. The caller is to delete this
6330 * field using decrRef() as it is no more needed.
6331 * \throw If the coordinates array is not set.
6332 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6333 * \throw If the connectivity data array has more than one component.
6334 * \throw If the connectivity data array has a named component.
6335 * \throw If the connectivity index data array has more than one component.
6336 * \throw If the connectivity index data array has a named component.
6337 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6338 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6339 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6341 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6344 int spaceDim=getSpaceDimension();
6345 int meshDim=getMeshDimension();
6346 if(spaceDim!=2 && spaceDim!=3)
6347 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6348 if(meshDim!=2 && meshDim!=3)
6349 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6350 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6352 int nbOfCells=getNumberOfCells();
6353 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6354 arr->alloc(nbOfCells,1);
6355 double *pt=arr->getPointer();
6356 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6357 const int *conn=_nodal_connec->getConstPointer();
6358 const int *connI=_nodal_connec_index->getConstPointer();
6359 const double *coo=_coords->getConstPointer();
6361 for(int i=0;i<nbOfCells;i++,pt++)
6363 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6366 case INTERP_KERNEL::NORM_TRI3:
6368 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6369 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6372 case INTERP_KERNEL::NORM_QUAD4:
6374 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6375 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6378 case INTERP_KERNEL::NORM_TETRA4:
6380 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6381 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6385 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6387 conn+=connI[i+1]-connI[i];
6389 ret->setName("EdgeRatio");
6390 ret->synchronizeTimeWithSupport();
6395 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6396 * cells. Currently cells of the following types are treated:
6397 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6398 * For a cell of other type an exception is thrown.
6399 * Space dimension of a 2D mesh can be either 2 or 3.
6400 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6401 * cells and one time, lying on \a this mesh. The caller is to delete this
6402 * field using decrRef() as it is no more needed.
6403 * \throw If the coordinates array is not set.
6404 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6405 * \throw If the connectivity data array has more than one component.
6406 * \throw If the connectivity data array has a named component.
6407 * \throw If the connectivity index data array has more than one component.
6408 * \throw If the connectivity index data array has a named component.
6409 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6410 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6411 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6413 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6416 int spaceDim=getSpaceDimension();
6417 int meshDim=getMeshDimension();
6418 if(spaceDim!=2 && spaceDim!=3)
6419 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6420 if(meshDim!=2 && meshDim!=3)
6421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6422 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6424 int nbOfCells=getNumberOfCells();
6425 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6426 arr->alloc(nbOfCells,1);
6427 double *pt=arr->getPointer();
6428 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6429 const int *conn=_nodal_connec->getConstPointer();
6430 const int *connI=_nodal_connec_index->getConstPointer();
6431 const double *coo=_coords->getConstPointer();
6433 for(int i=0;i<nbOfCells;i++,pt++)
6435 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6438 case INTERP_KERNEL::NORM_TRI3:
6440 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6441 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6444 case INTERP_KERNEL::NORM_QUAD4:
6446 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6447 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6450 case INTERP_KERNEL::NORM_TETRA4:
6452 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6453 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6457 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6459 conn+=connI[i+1]-connI[i];
6461 ret->setName("AspectRatio");
6462 ret->synchronizeTimeWithSupport();
6467 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6468 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6469 * treated: INTERP_KERNEL::NORM_QUAD4.
6470 * For a cell of other type an exception is thrown.
6471 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6472 * cells and one time, lying on \a this mesh. The caller is to delete this
6473 * field using decrRef() as it is no more needed.
6474 * \throw If the coordinates array is not set.
6475 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6476 * \throw If the connectivity data array has more than one component.
6477 * \throw If the connectivity data array has a named component.
6478 * \throw If the connectivity index data array has more than one component.
6479 * \throw If the connectivity index data array has a named component.
6480 * \throw If \a this->getMeshDimension() != 2.
6481 * \throw If \a this->getSpaceDimension() != 3.
6482 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6484 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6487 int spaceDim=getSpaceDimension();
6488 int meshDim=getMeshDimension();
6490 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6492 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6493 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6495 int nbOfCells=getNumberOfCells();
6496 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6497 arr->alloc(nbOfCells,1);
6498 double *pt=arr->getPointer();
6499 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6500 const int *conn=_nodal_connec->getConstPointer();
6501 const int *connI=_nodal_connec_index->getConstPointer();
6502 const double *coo=_coords->getConstPointer();
6504 for(int i=0;i<nbOfCells;i++,pt++)
6506 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6509 case INTERP_KERNEL::NORM_QUAD4:
6511 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6512 *pt=INTERP_KERNEL::quadWarp(tmp);
6516 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6518 conn+=connI[i+1]-connI[i];
6520 ret->setName("Warp");
6521 ret->synchronizeTimeWithSupport();
6527 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6528 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6529 * treated: INTERP_KERNEL::NORM_QUAD4.
6530 * For a cell of other type an exception is thrown.
6531 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6532 * cells and one time, lying on \a this mesh. The caller is to delete this
6533 * field using decrRef() as it is no more needed.
6534 * \throw If the coordinates array is not set.
6535 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6536 * \throw If the connectivity data array has more than one component.
6537 * \throw If the connectivity data array has a named component.
6538 * \throw If the connectivity index data array has more than one component.
6539 * \throw If the connectivity index data array has a named component.
6540 * \throw If \a this->getMeshDimension() != 2.
6541 * \throw If \a this->getSpaceDimension() != 3.
6542 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6544 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6547 int spaceDim=getSpaceDimension();
6548 int meshDim=getMeshDimension();
6550 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6552 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6553 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6555 int nbOfCells=getNumberOfCells();
6556 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6557 arr->alloc(nbOfCells,1);
6558 double *pt=arr->getPointer();
6559 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6560 const int *conn=_nodal_connec->getConstPointer();
6561 const int *connI=_nodal_connec_index->getConstPointer();
6562 const double *coo=_coords->getConstPointer();
6564 for(int i=0;i<nbOfCells;i++,pt++)
6566 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6569 case INTERP_KERNEL::NORM_QUAD4:
6571 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6572 *pt=INTERP_KERNEL::quadSkew(tmp);
6576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6578 conn+=connI[i+1]-connI[i];
6580 ret->setName("Skew");
6581 ret->synchronizeTimeWithSupport();
6586 * 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.
6588 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6590 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6592 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6595 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6597 std::set<INTERP_KERNEL::NormalizedCellType> types;
6598 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6599 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6600 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6601 arr->alloc(nbCells,1);
6602 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6604 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6606 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6609 ret->setName("Diameter");
6614 * This method aggregate the bbox of each cell and put it into bbox parameter.
6616 * \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)
6617 * For all other cases this input parameter is ignored.
6618 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6620 * \throw If \a this is not fully set (coordinates and connectivity).
6621 * \throw If a cell in \a this has no valid nodeId.
6622 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6624 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6626 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6627 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.
6628 return getBoundingBoxForBBTreeFast();
6629 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6631 bool presenceOfQuadratic(false);
6632 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6634 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6635 if(cm.isQuadratic())
6636 presenceOfQuadratic=true;
6638 if(!presenceOfQuadratic)
6639 return getBoundingBoxForBBTreeFast();
6640 if(mDim==2 && sDim==2)
6641 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6643 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6645 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) !");
6649 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6650 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6652 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6654 * \throw If \a this is not fully set (coordinates and connectivity).
6655 * \throw If a cell in \a this has no valid nodeId.
6657 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6659 checkFullyDefined();
6660 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6661 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6662 double *bbox(ret->getPointer());
6663 for(int i=0;i<nbOfCells*spaceDim;i++)
6665 bbox[2*i]=std::numeric_limits<double>::max();
6666 bbox[2*i+1]=-std::numeric_limits<double>::max();
6668 const double *coordsPtr(_coords->getConstPointer());
6669 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6670 for(int i=0;i<nbOfCells;i++)
6672 int offset=connI[i]+1;
6673 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6674 for(int j=0;j<nbOfNodesForCell;j++)
6676 int nodeId=conn[offset+j];
6677 if(nodeId>=0 && nodeId<nbOfNodes)
6679 for(int k=0;k<spaceDim;k++)
6681 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6682 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6689 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6690 throw INTERP_KERNEL::Exception(oss.str().c_str());
6697 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6698 * useful for 2D meshes having quadratic cells
6699 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6700 * the two extremities of the arc of circle).
6702 * \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)
6703 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6704 * \throw If \a this is not fully defined.
6705 * \throw If \a this is not a mesh with meshDimension equal to 2.
6706 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6707 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6709 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6711 checkFullyDefined();
6712 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6713 if(spaceDim!=2 || mDim!=2)
6714 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!");
6715 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6716 double *bbox(ret->getPointer());
6717 const double *coords(_coords->getConstPointer());
6718 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6719 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6721 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6722 int sz(connI[1]-connI[0]-1);
6723 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6724 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6725 INTERP_KERNEL::QuadraticPolygon *pol(0);
6726 for(int j=0;j<sz;j++)
6728 int nodeId(conn[*connI+1+j]);
6729 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6731 if(!cm.isQuadratic())
6732 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6734 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6735 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6736 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6742 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6743 * useful for 2D meshes having quadratic cells
6744 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6745 * the two extremities of the arc of circle).
6747 * \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)
6748 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6749 * \throw If \a this is not fully defined.
6750 * \throw If \a this is not a mesh with meshDimension equal to 1.
6751 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6752 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6754 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6756 checkFullyDefined();
6757 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6758 if(spaceDim!=2 || mDim!=1)
6759 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!");
6760 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6761 double *bbox(ret->getPointer());
6762 const double *coords(_coords->getConstPointer());
6763 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6764 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6766 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6767 int sz(connI[1]-connI[0]-1);
6768 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6769 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6770 INTERP_KERNEL::Edge *edge(0);
6771 for(int j=0;j<sz;j++)
6773 int nodeId(conn[*connI+1+j]);
6774 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6776 if(!cm.isQuadratic())
6777 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6779 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6780 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6781 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6788 namespace ParaMEDMEMImpl
6793 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6794 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6803 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6804 bool operator() (const int& pos) { return _conn[pos]==_val; }
6814 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6815 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6816 * \a this is composed in cell types.
6817 * The returned array is of size 3*n where n is the number of different types present in \a this.
6818 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6819 * This parameter is kept only for compatibility with other methode listed above.
6821 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6823 checkConnectivityFullyDefined();
6824 const int *conn=_nodal_connec->getConstPointer();
6825 const int *connI=_nodal_connec_index->getConstPointer();
6826 const int *work=connI;
6827 int nbOfCells=getNumberOfCells();
6828 std::size_t n=getAllGeoTypes().size();
6829 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6830 std::set<INTERP_KERNEL::NormalizedCellType> types;
6831 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6833 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6834 if(types.find(typ)!=types.end())
6836 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6837 oss << " is not contiguous !";
6838 throw INTERP_KERNEL::Exception(oss.str().c_str());
6842 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6843 ret[3*i+1]=(int)std::distance(work,work2);
6850 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6851 * only for types cell, type node is not managed.
6852 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6853 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6854 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6855 * If 2 or more same geometric type is in \a code and exception is thrown too.
6857 * This method firstly checks
6858 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6859 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6860 * an exception is thrown too.
6862 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6863 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6864 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6866 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6870 std::size_t sz=code.size();
6873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6874 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6876 bool isNoPflUsed=true;
6877 for(std::size_t i=0;i<n;i++)
6878 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6880 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6882 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6883 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6884 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6890 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6892 if(types.size()==_types.size())
6895 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6897 int *retPtr=ret->getPointer();
6898 const int *connI=_nodal_connec_index->getConstPointer();
6899 const int *conn=_nodal_connec->getConstPointer();
6900 int nbOfCells=getNumberOfCells();
6903 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6905 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6906 int offset=(int)std::distance(connI,i);
6907 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6908 int nbOfCellsOfCurType=(int)std::distance(i,j);
6909 if(code[3*kk+2]==-1)
6910 for(int k=0;k<nbOfCellsOfCurType;k++)
6914 int idInIdsPerType=code[3*kk+2];
6915 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6917 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6920 zePfl->checkAllocated();
6921 if(zePfl->getNumberOfComponents()==1)
6923 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6925 if(*k>=0 && *k<nbOfCellsOfCurType)
6926 *retPtr=(*k)+offset;
6929 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6930 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6931 throw INTERP_KERNEL::Exception(oss.str().c_str());
6936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6943 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6944 oss << " should be in [0," << idsPerType.size() << ") !";
6945 throw INTERP_KERNEL::Exception(oss.str().c_str());
6954 * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6955 * 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.
6956 * 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.
6957 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6959 * \param [in] profile
6960 * \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.
6961 * \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,
6962 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6963 * \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.
6964 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6965 * \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
6967 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6970 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6971 if(profile->getNumberOfComponents()!=1)
6972 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6973 checkConnectivityFullyDefined();
6974 const int *conn=_nodal_connec->getConstPointer();
6975 const int *connI=_nodal_connec_index->getConstPointer();
6976 int nbOfCells=getNumberOfCells();
6977 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6978 std::vector<int> typeRangeVals(1);
6979 for(const int *i=connI;i!=connI+nbOfCells;)
6981 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6982 if(std::find(types.begin(),types.end(),curType)!=types.end())
6984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6986 types.push_back(curType);
6987 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6988 typeRangeVals.push_back((int)std::distance(connI,i));
6991 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6992 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6994 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6995 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6997 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6998 code.resize(3*nbOfCastsFinal);
6999 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7000 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7001 for(int i=0;i<nbOfCastsFinal;i++)
7003 int castId=castsPresent->getIJ(i,0);
7004 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7005 idsInPflPerType2.push_back(tmp3);
7006 code[3*i]=(int)types[castId];
7007 code[3*i+1]=tmp3->getNumberOfTuples();
7008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7009 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
7011 tmp4->copyStringInfoFrom(*profile);
7012 idsPerType2.push_back(tmp4);
7013 code[3*i+2]=(int)idsPerType2.size()-1;
7020 std::size_t sz2=idsInPflPerType2.size();
7021 idsInPflPerType.resize(sz2);
7022 for(std::size_t i=0;i<sz2;i++)
7024 DataArrayInt *locDa=idsInPflPerType2[i];
7026 idsInPflPerType[i]=locDa;
7028 std::size_t sz=idsPerType2.size();
7029 idsPerType.resize(sz);
7030 for(std::size_t i=0;i<sz;i++)
7032 DataArrayInt *locDa=idsPerType2[i];
7034 idsPerType[i]=locDa;
7039 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7040 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7041 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7042 * 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.
7044 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7046 checkFullyDefined();
7047 nM1LevMesh->checkFullyDefined();
7048 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7050 if(_coords!=nM1LevMesh->getCoords())
7051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7053 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7054 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7056 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7057 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7058 tmp->setConnectivity(tmp0,tmp1);
7059 tmp->renumberCells(ret0->getConstPointer(),false);
7060 revDesc=tmp->getNodalConnectivity();
7061 revDescIndx=tmp->getNodalConnectivityIndex();
7062 DataArrayInt *ret=0;
7063 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7066 ret->getMaxValue(tmp2);
7068 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7069 throw INTERP_KERNEL::Exception(oss.str().c_str());
7074 revDescIndx->incrRef();
7077 meshnM1Old2New=ret0;
7082 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7083 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7084 * in "Old to New" mode.
7085 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7086 * this array using decrRef() as it is no more needed.
7087 * \throw If the nodal connectivity of cells is not defined.
7089 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7091 checkConnectivityFullyDefined();
7092 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7093 renumberCells(ret->getConstPointer(),false);
7098 * This methods checks that cells are sorted by their types.
7099 * This method makes asumption (no check) that connectivity is correctly set before calling.
7101 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7103 checkFullyDefined();
7104 const int *conn=_nodal_connec->getConstPointer();
7105 const int *connI=_nodal_connec_index->getConstPointer();
7106 int nbOfCells=getNumberOfCells();
7107 std::set<INTERP_KERNEL::NormalizedCellType> types;
7108 for(const int *i=connI;i!=connI+nbOfCells;)
7110 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7111 if(types.find(curType)!=types.end())
7113 types.insert(curType);
7114 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7120 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7121 * The geometric type order is specified by MED file.
7123 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7125 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7127 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7131 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7132 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7133 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7134 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7136 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7138 checkFullyDefined();
7139 const int *conn=_nodal_connec->getConstPointer();
7140 const int *connI=_nodal_connec_index->getConstPointer();
7141 int nbOfCells=getNumberOfCells();
7145 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7146 for(const int *i=connI;i!=connI+nbOfCells;)
7148 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7149 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7150 if(isTypeExists!=orderEnd)
7152 int pos=(int)std::distance(orderBg,isTypeExists);
7156 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7160 if(sg.find(curType)==sg.end())
7162 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7173 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7174 * 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
7175 * 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'.
7177 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7179 checkConnectivityFullyDefined();
7180 int nbOfCells=getNumberOfCells();
7181 const int *conn=_nodal_connec->getConstPointer();
7182 const int *connI=_nodal_connec_index->getConstPointer();
7183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7185 tmpa->alloc(nbOfCells,1);
7186 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7187 tmpb->fillWithZero();
7188 int *tmp=tmpa->getPointer();
7189 int *tmp2=tmpb->getPointer();
7190 for(const int *i=connI;i!=connI+nbOfCells;i++)
7192 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7195 int pos=(int)std::distance(orderBg,where);
7197 tmp[std::distance(connI,i)]=pos;
7201 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7202 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7203 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7204 throw INTERP_KERNEL::Exception(oss.str().c_str());
7207 nbPerType=tmpb.retn();
7212 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7214 * \return a new object containing the old to new correspondance.
7216 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7218 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7220 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7224 * 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.
7225 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7226 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7227 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7229 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7231 DataArrayInt *nbPerType=0;
7232 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7233 nbPerType->decrRef();
7234 return tmpa->buildPermArrPerLevel();
7238 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7239 * The number of cells remains unchanged after the call of this method.
7240 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7241 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7243 * \return the array giving the correspondance old to new.
7245 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7247 checkFullyDefined();
7249 const int *conn=_nodal_connec->getConstPointer();
7250 const int *connI=_nodal_connec_index->getConstPointer();
7251 int nbOfCells=getNumberOfCells();
7252 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7253 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7254 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7256 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7257 types.push_back(curType);
7258 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7260 DataArrayInt *ret=DataArrayInt::New();
7261 ret->alloc(nbOfCells,1);
7262 int *retPtr=ret->getPointer();
7263 std::fill(retPtr,retPtr+nbOfCells,-1);
7265 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7267 for(const int *i=connI;i!=connI+nbOfCells;i++)
7268 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7269 retPtr[std::distance(connI,i)]=newCellId++;
7271 renumberCells(retPtr,false);
7276 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7277 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7278 * This method makes asumption that connectivity is correctly set before calling.
7280 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7282 checkConnectivityFullyDefined();
7283 const int *conn=_nodal_connec->getConstPointer();
7284 const int *connI=_nodal_connec_index->getConstPointer();
7285 int nbOfCells=getNumberOfCells();
7286 std::vector<MEDCouplingUMesh *> ret;
7287 for(const int *i=connI;i!=connI+nbOfCells;)
7289 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7290 int beginCellId=(int)std::distance(connI,i);
7291 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7292 int endCellId=(int)std::distance(connI,i);
7293 int sz=endCellId-beginCellId;
7294 int *cells=new int[sz];
7295 for(int j=0;j<sz;j++)
7296 cells[j]=beginCellId+j;
7297 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7305 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7306 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7307 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7309 * \return a newly allocated instance, that the caller must manage.
7310 * \throw If \a this contains more than one geometric type.
7311 * \throw If the nodal connectivity of \a this is not fully defined.
7312 * \throw If the internal data is not coherent.
7314 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7316 checkConnectivityFullyDefined();
7317 if(_types.size()!=1)
7318 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7319 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7320 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7321 ret->setCoords(getCoords());
7322 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7326 retC->setNodalConnectivity(c);
7330 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7332 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7333 DataArrayInt *c=0,*ci=0;
7334 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7336 retD->setNodalConnectivity(cs,cis);
7341 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7343 checkConnectivityFullyDefined();
7344 if(_types.size()!=1)
7345 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7346 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7347 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7350 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7351 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7352 throw INTERP_KERNEL::Exception(oss.str().c_str());
7354 int nbCells=getNumberOfCells();
7356 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7358 int *outPtr=connOut->getPointer();
7359 const int *conn=_nodal_connec->begin();
7360 const int *connI=_nodal_connec_index->begin();
7362 for(int i=0;i<nbCells;i++,connI++)
7364 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7365 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7368 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 << ") !";
7369 throw INTERP_KERNEL::Exception(oss.str().c_str());
7372 return connOut.retn();
7376 * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7377 * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7381 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7383 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7384 checkConnectivityFullyDefined();
7385 if(_types.size()!=1)
7386 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7387 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7389 throw INTERP_KERNEL::Exception(msg0);
7390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7391 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7392 int *cp(c->getPointer()),*cip(ci->getPointer());
7393 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7395 for(int i=0;i<nbCells;i++,cip++,incip++)
7397 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7398 int delta(stop-strt);
7401 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7402 cp=std::copy(incp+strt,incp+stop,cp);
7404 throw INTERP_KERNEL::Exception(msg0);
7407 throw INTERP_KERNEL::Exception(msg0);
7408 cip[1]=cip[0]+delta;
7410 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7414 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7415 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7416 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7417 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7418 * are not used here to avoid the build of big permutation array.
7420 * \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
7421 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7422 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7423 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7424 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7425 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7426 * \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
7427 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7429 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7430 DataArrayInt *&szOfCellGrpOfSameType,
7431 DataArrayInt *&idInMsOfCellGrpOfSameType)
7433 std::vector<const MEDCouplingUMesh *> ms2;
7434 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7437 (*it)->checkConnectivityFullyDefined();
7441 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7442 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7443 int meshDim=ms2[0]->getMeshDimension();
7444 std::vector<const MEDCouplingUMesh *> m1ssm;
7445 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7447 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7448 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7451 ret1->alloc(0,1); ret2->alloc(0,1);
7452 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7454 if(meshDim!=(*it)->getMeshDimension())
7455 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7456 if(refCoo!=(*it)->getCoords())
7457 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7458 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7459 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7460 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7461 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7463 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7464 m1ssmSingleAuto.push_back(singleCell);
7465 m1ssmSingle.push_back(singleCell);
7466 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7469 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7471 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7472 for(std::size_t i=0;i<m1ssm.size();i++)
7473 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7474 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7475 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7476 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7481 * This method returns a newly created DataArrayInt instance.
7482 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7484 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7486 checkFullyDefined();
7487 const int *conn=_nodal_connec->getConstPointer();
7488 const int *connIndex=_nodal_connec_index->getConstPointer();
7489 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7490 for(const int *w=begin;w!=end;w++)
7491 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7492 ret->pushBackSilent(*w);
7497 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7498 * are in [0:getNumberOfCells())
7500 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7502 checkFullyDefined();
7503 const int *conn=_nodal_connec->getConstPointer();
7504 const int *connI=_nodal_connec_index->getConstPointer();
7505 int nbOfCells=getNumberOfCells();
7506 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7507 int *tmp=new int[nbOfCells];
7508 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7511 for(const int *i=connI;i!=connI+nbOfCells;i++)
7512 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7513 tmp[std::distance(connI,i)]=j++;
7515 DataArrayInt *ret=DataArrayInt::New();
7516 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7517 ret->copyStringInfoFrom(*da);
7518 int *retPtr=ret->getPointer();
7519 const int *daPtr=da->getConstPointer();
7520 int nbOfElems=da->getNbOfElems();
7521 for(int k=0;k<nbOfElems;k++)
7522 retPtr[k]=tmp[daPtr[k]];
7528 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7529 * This method \b works \b for mesh sorted by type.
7530 * cells whose ids is in 'idsPerGeoType' array.
7531 * This method conserves coords and name of mesh.
7533 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7535 std::vector<int> code=getDistributionOfTypes();
7536 std::size_t nOfTypesInThis=code.size()/3;
7537 int sz=0,szOfType=0;
7538 for(std::size_t i=0;i<nOfTypesInThis;i++)
7543 szOfType=code[3*i+1];
7545 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7546 if(*work<0 || *work>=szOfType)
7548 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7549 oss << ". It should be in [0," << szOfType << ") !";
7550 throw INTERP_KERNEL::Exception(oss.str().c_str());
7552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7553 int *idsPtr=idsTokeep->getPointer();
7555 for(std::size_t i=0;i<nOfTypesInThis;i++)
7558 for(int j=0;j<code[3*i+1];j++)
7561 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7562 offset+=code[3*i+1];
7564 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7565 ret->copyTinyInfoFrom(this);
7570 * This method returns a vector of size 'this->getNumberOfCells()'.
7571 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7573 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7575 int ncell=getNumberOfCells();
7576 std::vector<bool> ret(ncell);
7577 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7578 const int *c=getNodalConnectivity()->getConstPointer();
7579 for(int i=0;i<ncell;i++)
7581 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7582 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7583 ret[i]=cm.isQuadratic();
7589 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7591 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7593 if(other->getType()!=UNSTRUCTURED)
7594 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7595 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7596 return MergeUMeshes(this,otherC);
7600 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7601 * computed by averaging coordinates of cell nodes, so this method is not a right
7602 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7603 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7604 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7605 * components. The caller is to delete this array using decrRef() as it is
7607 * \throw If the coordinates array is not set.
7608 * \throw If the nodal connectivity of cells is not defined.
7609 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7611 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7613 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7614 int spaceDim=getSpaceDimension();
7615 int nbOfCells=getNumberOfCells();
7616 ret->alloc(nbOfCells,spaceDim);
7617 ret->copyStringInfoFrom(*getCoords());
7618 double *ptToFill=ret->getPointer();
7619 const int *nodal=_nodal_connec->getConstPointer();
7620 const int *nodalI=_nodal_connec_index->getConstPointer();
7621 const double *coor=_coords->getConstPointer();
7622 for(int i=0;i<nbOfCells;i++)
7624 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7625 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7632 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7633 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7635 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7636 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7638 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7639 * \throw If \a this is not fully defined (coordinates and connectivity)
7640 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7642 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7644 checkFullyDefined();
7645 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7646 int spaceDim=getSpaceDimension();
7647 int nbOfCells=getNumberOfCells();
7648 int nbOfNodes=getNumberOfNodes();
7649 ret->alloc(nbOfCells,spaceDim);
7650 double *ptToFill=ret->getPointer();
7651 const int *nodal=_nodal_connec->getConstPointer();
7652 const int *nodalI=_nodal_connec_index->getConstPointer();
7653 const double *coor=_coords->getConstPointer();
7654 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7656 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7657 std::fill(ptToFill,ptToFill+spaceDim,0.);
7658 if(type!=INTERP_KERNEL::NORM_POLYHED)
7660 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7662 if(*conn>=0 && *conn<nbOfNodes)
7663 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7666 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7667 throw INTERP_KERNEL::Exception(oss.str().c_str());
7670 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7671 if(nbOfNodesInCell>0)
7672 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7675 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7676 throw INTERP_KERNEL::Exception(oss.str().c_str());
7681 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7683 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7685 if(*it>=0 && *it<nbOfNodes)
7686 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7689 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7690 throw INTERP_KERNEL::Exception(oss.str().c_str());
7694 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7697 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7698 throw INTERP_KERNEL::Exception(oss.str().c_str());
7706 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7707 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7708 * are specified via an array of cell ids.
7709 * \warning Validity of the specified cell ids is not checked!
7710 * Valid range is [ 0, \a this->getNumberOfCells() ).
7711 * \param [in] begin - an array of cell ids of interest.
7712 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7713 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7714 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7715 * caller is to delete this array using decrRef() as it is no more needed.
7716 * \throw If the coordinates array is not set.
7717 * \throw If the nodal connectivity of cells is not defined.
7719 * \if ENABLE_EXAMPLES
7720 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7721 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7724 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7726 DataArrayDouble *ret=DataArrayDouble::New();
7727 int spaceDim=getSpaceDimension();
7728 int nbOfTuple=(int)std::distance(begin,end);
7729 ret->alloc(nbOfTuple,spaceDim);
7730 double *ptToFill=ret->getPointer();
7731 double *tmp=new double[spaceDim];
7732 const int *nodal=_nodal_connec->getConstPointer();
7733 const int *nodalI=_nodal_connec_index->getConstPointer();
7734 const double *coor=_coords->getConstPointer();
7735 for(const int *w=begin;w!=end;w++)
7737 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7738 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7746 * 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".
7747 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7748 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7749 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7750 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7752 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7753 * \throw If spaceDim!=3 or meshDim!=2.
7754 * \throw If connectivity of \a this is invalid.
7755 * \throw If connectivity of a cell in \a this points to an invalid node.
7757 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7759 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7760 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7761 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7762 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7763 ret->alloc(nbOfCells,4);
7764 double *retPtr(ret->getPointer());
7765 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7766 const double *coor(_coords->begin());
7767 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7769 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7770 if(nodalI[1]-nodalI[0]>=3)
7772 for(int j=0;j<3;j++)
7774 int nodeId(nodal[nodalI[0]+1+j]);
7775 if(nodeId>=0 && nodeId<nbOfNodes)
7776 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7779 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7780 throw INTERP_KERNEL::Exception(oss.str().c_str());
7786 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7787 throw INTERP_KERNEL::Exception(oss.str().c_str());
7789 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7790 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7796 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7799 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7802 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7803 da->checkAllocated();
7804 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7806 int nbOfTuples=da->getNumberOfTuples();
7807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7809 c->alloc(2*nbOfTuples,1);
7810 cI->alloc(nbOfTuples+1,1);
7811 int *cp=c->getPointer();
7812 int *cip=cI->getPointer();
7814 for(int i=0;i<nbOfTuples;i++)
7816 *cp++=INTERP_KERNEL::NORM_POINT1;
7820 ret->setConnectivity(c,cI,true);
7824 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7825 * Cells and nodes of
7826 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7827 * \param [in] mesh1 - the first mesh.
7828 * \param [in] mesh2 - the second mesh.
7829 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7830 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7831 * is no more needed.
7832 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7833 * \throw If the coordinates array is not set in none of the meshes.
7834 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7835 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7837 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7839 std::vector<const MEDCouplingUMesh *> tmp(2);
7840 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7841 return MergeUMeshes(tmp);
7845 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7846 * Cells and nodes of
7847 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7848 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7849 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7850 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7851 * is no more needed.
7852 * \throw If \a a.size() == 0.
7853 * \throw If \a a[ *i* ] == NULL.
7854 * \throw If the coordinates array is not set in none of the meshes.
7855 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7856 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7858 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7860 std::size_t sz=a.size();
7862 return MergeUMeshesLL(a);
7863 for(std::size_t ii=0;ii<sz;ii++)
7866 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7867 throw INTERP_KERNEL::Exception(oss.str().c_str());
7869 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7870 std::vector< const MEDCouplingUMesh * > aa(sz);
7872 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7874 const MEDCouplingUMesh *cur=a[i];
7875 const DataArrayDouble *coo=cur->getCoords();
7877 spaceDim=coo->getNumberOfComponents();
7880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7881 for(std::size_t i=0;i<sz;i++)
7883 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7886 return MergeUMeshesLL(aa);
7891 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7894 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7895 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7896 int meshDim=(*it)->getMeshDimension();
7897 int nbOfCells=(*it)->getNumberOfCells();
7898 int meshLgth=(*it++)->getMeshLength();
7899 for(;it!=a.end();it++)
7901 if(meshDim!=(*it)->getMeshDimension())
7902 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7903 nbOfCells+=(*it)->getNumberOfCells();
7904 meshLgth+=(*it)->getMeshLength();
7906 std::vector<const MEDCouplingPointSet *> aps(a.size());
7907 std::copy(a.begin(),a.end(),aps.begin());
7908 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7909 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7910 ret->setCoords(pts);
7911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7912 c->alloc(meshLgth,1);
7913 int *cPtr=c->getPointer();
7914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7915 cI->alloc(nbOfCells+1,1);
7916 int *cIPtr=cI->getPointer();
7920 for(it=a.begin();it!=a.end();it++)
7922 int curNbOfCell=(*it)->getNumberOfCells();
7923 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7924 const int *curC=(*it)->_nodal_connec->getConstPointer();
7925 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7926 for(int j=0;j<curNbOfCell;j++)
7928 const int *src=curC+curCI[j];
7930 for(;src!=curC+curCI[j+1];src++,cPtr++)
7938 offset+=curCI[curNbOfCell];
7939 offset2+=(*it)->getNumberOfNodes();
7942 ret->setConnectivity(c,cI,true);
7949 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7950 * dimension and sharing the node coordinates array.
7951 * All cells of the first mesh precede all cells of the second mesh
7952 * within the result mesh.
7953 * \param [in] mesh1 - the first mesh.
7954 * \param [in] mesh2 - the second mesh.
7955 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7956 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7957 * is no more needed.
7958 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7959 * \throw If the meshes do not share the node coordinates array.
7960 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7961 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7963 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7965 std::vector<const MEDCouplingUMesh *> tmp(2);
7966 tmp[0]=mesh1; tmp[1]=mesh2;
7967 return MergeUMeshesOnSameCoords(tmp);
7971 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7972 * dimension and sharing the node coordinates array.
7973 * All cells of the *i*-th mesh precede all cells of the
7974 * (*i*+1)-th mesh within the result mesh.
7975 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7976 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7977 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7978 * is no more needed.
7979 * \throw If \a a.size() == 0.
7980 * \throw If \a a[ *i* ] == NULL.
7981 * \throw If the meshes do not share the node coordinates array.
7982 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7983 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7985 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7988 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7989 for(std::size_t ii=0;ii<meshes.size();ii++)
7992 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7993 throw INTERP_KERNEL::Exception(oss.str().c_str());
7995 const DataArrayDouble *coords=meshes.front()->getCoords();
7996 int meshDim=meshes.front()->getMeshDimension();
7997 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7999 int meshIndexLgth=0;
8000 for(;iter!=meshes.end();iter++)
8002 if(coords!=(*iter)->getCoords())
8003 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8004 if(meshDim!=(*iter)->getMeshDimension())
8005 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8006 meshLgth+=(*iter)->getMeshLength();
8007 meshIndexLgth+=(*iter)->getNumberOfCells();
8009 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8010 nodal->alloc(meshLgth,1);
8011 int *nodalPtr=nodal->getPointer();
8012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8013 nodalIndex->alloc(meshIndexLgth+1,1);
8014 int *nodalIndexPtr=nodalIndex->getPointer();
8016 for(iter=meshes.begin();iter!=meshes.end();iter++)
8018 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8019 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8020 int nbOfCells=(*iter)->getNumberOfCells();
8021 int meshLgth2=(*iter)->getMeshLength();
8022 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8023 if(iter!=meshes.begin())
8024 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8026 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8029 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8030 ret->setName("merge");
8031 ret->setMeshDimension(meshDim);
8032 ret->setConnectivity(nodal,nodalIndex,true);
8033 ret->setCoords(coords);
8038 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8039 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8040 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8041 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8042 * New" mode are returned for each input mesh.
8043 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8044 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8045 * valid values [0,1,2], see zipConnectivityTraducer().
8046 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8047 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8048 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8050 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8051 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8052 * is no more needed.
8053 * \throw If \a meshes.size() == 0.
8054 * \throw If \a meshes[ *i* ] == NULL.
8055 * \throw If the meshes do not share the node coordinates array.
8056 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8057 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8058 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8059 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8061 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8063 //All checks are delegated to MergeUMeshesOnSameCoords
8064 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8066 corr.resize(meshes.size());
8067 std::size_t nbOfMeshes=meshes.size();
8069 const int *o2nPtr=o2n->getConstPointer();
8070 for(std::size_t i=0;i<nbOfMeshes;i++)
8072 DataArrayInt *tmp=DataArrayInt::New();
8073 int curNbOfCells=meshes[i]->getNumberOfCells();
8074 tmp->alloc(curNbOfCells,1);
8075 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8076 offset+=curNbOfCells;
8077 tmp->setName(meshes[i]->getName());
8084 * Makes all given meshes share the nodal connectivity array. The common connectivity
8085 * array is created by concatenating the connectivity arrays of all given meshes. All
8086 * the given meshes must be of the same space dimension but dimension of cells **can
8087 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8088 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8089 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8090 * \param [in,out] meshes - a vector of meshes to update.
8091 * \throw If any of \a meshes is NULL.
8092 * \throw If the coordinates array is not set in any of \a meshes.
8093 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8094 * \throw If \a meshes are of different space dimension.
8096 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8098 std::size_t sz=meshes.size();
8101 std::vector< const DataArrayDouble * > coords(meshes.size());
8102 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8103 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8107 (*it)->checkConnectivityFullyDefined();
8108 const DataArrayDouble *coo=(*it)->getCoords();
8113 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8114 oss << " has no coordinate array defined !";
8115 throw INTERP_KERNEL::Exception(oss.str().c_str());
8120 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8121 oss << " is null !";
8122 throw INTERP_KERNEL::Exception(oss.str().c_str());
8125 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8126 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8127 int offset=(*it)->getNumberOfNodes();
8128 (*it++)->setCoords(res);
8129 for(;it!=meshes.end();it++)
8131 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8132 (*it)->setCoords(res);
8133 (*it)->shiftNodeNumbersInConn(offset);
8134 offset+=oldNumberOfNodes;
8139 * Merges nodes coincident with a given precision within all given meshes that share
8140 * the nodal connectivity array. The given meshes **can be of different** mesh
8141 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8142 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8143 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8144 * \param [in,out] meshes - a vector of meshes to update.
8145 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8146 * \throw If any of \a meshes is NULL.
8147 * \throw If the \a meshes do not share the same node coordinates array.
8148 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8150 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8154 std::set<const DataArrayDouble *> s;
8155 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8158 s.insert((*it)->getCoords());
8161 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 !";
8162 throw INTERP_KERNEL::Exception(oss.str().c_str());
8167 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 !";
8168 throw INTERP_KERNEL::Exception(oss.str().c_str());
8170 const DataArrayDouble *coo=*(s.begin());
8174 DataArrayInt *comm,*commI;
8175 coo->findCommonTuples(eps,-1,comm,commI);
8176 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8177 int oldNbOfNodes=coo->getNumberOfTuples();
8179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8180 if(oldNbOfNodes==newNbOfNodes)
8182 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8183 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8185 (*it)->renumberNodesInConn(o2n->getConstPointer());
8186 (*it)->setCoords(newCoords);
8191 * 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.
8192 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8193 * \param isQuad specifies the policy of connectivity.
8194 * @ret in/out parameter in which the result will be append
8196 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8198 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8199 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8200 ret.push_back(cm.getExtrudedType());
8201 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8204 case INTERP_KERNEL::NORM_POINT1:
8206 ret.push_back(connBg[1]);
8207 ret.push_back(connBg[1]+nbOfNodesPerLev);
8210 case INTERP_KERNEL::NORM_SEG2:
8212 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8213 ret.insert(ret.end(),conn,conn+4);
8216 case INTERP_KERNEL::NORM_SEG3:
8218 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8219 ret.insert(ret.end(),conn,conn+8);
8222 case INTERP_KERNEL::NORM_QUAD4:
8224 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8225 ret.insert(ret.end(),conn,conn+8);
8228 case INTERP_KERNEL::NORM_TRI3:
8230 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8231 ret.insert(ret.end(),conn,conn+6);
8234 case INTERP_KERNEL::NORM_TRI6:
8236 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,
8237 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8238 ret.insert(ret.end(),conn,conn+15);
8241 case INTERP_KERNEL::NORM_QUAD8:
8244 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8245 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8246 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8248 ret.insert(ret.end(),conn,conn+20);
8251 case INTERP_KERNEL::NORM_POLYGON:
8253 std::back_insert_iterator< std::vector<int> > ii(ret);
8254 std::copy(connBg+1,connEnd,ii);
8256 std::reverse_iterator<const int *> rConnBg(connEnd);
8257 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8258 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8259 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8260 for(std::size_t i=0;i<nbOfRadFaces;i++)
8263 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8264 std::copy(conn,conn+4,ii);
8269 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8274 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8276 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8279 double v[3]={0.,0.,0.};
8280 std::size_t sz=std::distance(begin,end);
8285 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];
8286 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8287 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8289 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8291 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8292 // SEG3 forming a circle):
8293 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8295 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8296 for(std::size_t j=0;j<sz;j++)
8298 if (j%2) // current point i is quadratic, next point i+1 is standard
8301 ip1 = (j+1)%sz; // ip1 = "i+1"
8303 else // current point i is standard, next point i+1 is quadratic
8308 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8309 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8310 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8312 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8318 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8320 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8322 std::vector<std::pair<int,int> > edges;
8323 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8324 const int *bgFace=begin;
8325 for(std::size_t i=0;i<nbOfFaces;i++)
8327 const int *endFace=std::find(bgFace+1,end,-1);
8328 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8329 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8331 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8332 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8334 edges.push_back(p1);
8338 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8342 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8344 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8346 double vec0[3],vec1[3];
8347 std::size_t sz=std::distance(begin,end);
8349 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8350 int nbOfNodes=(int)sz/2;
8351 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8352 const double *pt0=coords+3*begin[0];
8353 const double *pt1=coords+3*begin[nbOfNodes];
8354 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8355 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8358 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8360 std::size_t sz=std::distance(begin,end);
8361 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8362 std::size_t nbOfNodes(sz/2);
8363 std::copy(begin,end,(int *)tmp);
8364 for(std::size_t j=1;j<nbOfNodes;j++)
8366 begin[j]=tmp[nbOfNodes-j];
8367 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8371 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8373 std::size_t sz=std::distance(begin,end);
8375 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8376 double vec0[3],vec1[3];
8377 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8378 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];
8379 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;
8382 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8384 std::size_t sz=std::distance(begin,end);
8386 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8388 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8389 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8390 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8394 * 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 )
8395 * 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
8398 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8399 * \param [in] coords the coordinates with nb of components exactly equal to 3
8400 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8401 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8402 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8404 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8406 int nbFaces=std::count(begin+1,end,-1)+1;
8407 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8408 double *vPtr=v->getPointer();
8409 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8410 double *pPtr=p->getPointer();
8411 const int *stFaceConn=begin+1;
8412 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8414 const int *endFaceConn=std::find(stFaceConn,end,-1);
8415 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8416 stFaceConn=endFaceConn+1;
8418 pPtr=p->getPointer(); vPtr=v->getPointer();
8419 DataArrayInt *comm1=0,*commI1=0;
8420 v->findCommonTuples(eps,-1,comm1,commI1);
8421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8422 const int *comm1Ptr=comm1->getConstPointer();
8423 const int *commI1Ptr=commI1->getConstPointer();
8424 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8425 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8427 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8428 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8429 mm->finishInsertingCells();
8431 for(int i=0;i<nbOfGrps1;i++)
8433 int vecId=comm1Ptr[commI1Ptr[i]];
8434 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8435 DataArrayInt *comm2=0,*commI2=0;
8436 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8437 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8438 const int *comm2Ptr=comm2->getConstPointer();
8439 const int *commI2Ptr=commI2->getConstPointer();
8440 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8441 for(int j=0;j<nbOfGrps2;j++)
8443 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8445 res->insertAtTheEnd(begin,end);
8446 res->pushBackSilent(-1);
8450 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8452 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8453 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8454 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8455 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8458 const int *idsNodePtr=idsNode->getConstPointer();
8459 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];
8460 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8461 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8462 if(std::abs(norm)>eps)
8464 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8465 mm3->rotate(center,vec,angle);
8467 mm3->changeSpaceDimension(2);
8468 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8469 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8470 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8471 int nbOfCells=mm4->getNumberOfCells();
8472 for(int k=0;k<nbOfCells;k++)
8475 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8476 res->pushBackSilent(idsNodePtr[*work]);
8477 res->pushBackSilent(-1);
8482 res->popBackSilent();
8486 * 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
8487 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8489 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8490 * \param [in] coords coordinates expected to have 3 components.
8491 * \param [in] begin start of the nodal connectivity of the face.
8492 * \param [in] end end of the nodal connectivity (excluded) of the face.
8493 * \param [out] v the normalized vector of size 3
8494 * \param [out] p the pos of plane
8496 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8498 std::size_t nbPoints=std::distance(begin,end);
8500 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8501 double vec[3]={0.,0.,0.};
8503 bool refFound=false;
8504 for(;j<nbPoints-1 && !refFound;j++)
8506 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8507 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8508 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8509 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8513 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8516 for(std::size_t i=j;i<nbPoints-1;i++)
8519 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8520 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8521 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8522 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8525 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8526 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];
8527 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8530 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8531 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8535 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8539 * This method tries to obtain a well oriented polyhedron.
8540 * If the algorithm fails, an exception will be thrown.
8542 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8544 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8545 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8546 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8548 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8549 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8550 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8552 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8555 std::size_t smthChanged=0;
8556 for(std::size_t i=0;i<nbOfFaces;i++)
8558 endFace=std::find(bgFace+1,end,-1);
8559 nbOfEdgesInFace=std::distance(bgFace,endFace);
8563 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8565 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8566 std::pair<int,int> p2(p1.second,p1.first);
8567 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8568 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8569 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8574 std::reverse(bgFace+1,endFace);
8575 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8577 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8578 std::pair<int,int> p2(p1.second,p1.first);
8579 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8580 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8581 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8582 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8583 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8584 if(it!=edgesOK.end())
8587 edgesFinished.push_back(p1);
8590 edgesOK.push_back(p1);
8597 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8599 if(!edgesOK.empty())
8600 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8601 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8602 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8604 for(std::size_t i=0;i<nbOfFaces;i++)
8606 endFace=std::find(bgFace+1,end,-1);
8607 std::reverse(bgFace+1,endFace);
8613 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8615 int nbOfNodesExpected(skin->getNumberOfNodes());
8616 const int *n2oPtr(n2o->getConstPointer());
8617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8618 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8619 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8620 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8621 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8622 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8623 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8624 if(nbOfNodesExpected<1)
8626 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8627 *work++=n2oPtr[prevNode];
8628 for(int i=1;i<nbOfNodesExpected;i++)
8630 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8632 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8633 conn.erase(prevNode);
8636 int curNode(*(conn.begin()));
8637 *work++=n2oPtr[curNode];
8638 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8639 shar.erase(prevCell);
8642 prevCell=*(shar.begin());
8646 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8649 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8657 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8659 int nbOfNodesExpected(skin->getNumberOfNodes());
8660 int nbOfTurn(nbOfNodesExpected/2);
8661 const int *n2oPtr(n2o->getConstPointer());
8662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8663 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8664 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8665 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8666 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8668 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8669 if(nbOfNodesExpected<1)
8671 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8672 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8673 for(int i=1;i<nbOfTurn;i++)
8675 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8677 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8678 conn.erase(prevNode);
8681 int curNode(*(conn.begin()));
8682 *work=n2oPtr[curNode];
8683 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8684 shar.erase(prevCell);
8687 int curCell(*(shar.begin()));
8688 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8697 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8706 * This method makes the assumption spacedimension == meshdimension == 2.
8707 * This method works only for linear cells.
8709 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8711 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8713 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8714 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8715 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8716 int oldNbOfNodes(skin->getNumberOfNodes());
8717 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8718 int nbOfNodesExpected(skin->getNumberOfNodes());
8719 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8720 int nbCells(skin->getNumberOfCells());
8721 if(nbCells==nbOfNodesExpected)
8722 return buildUnionOf2DMeshLinear(skin,n2o);
8723 else if(2*nbCells==nbOfNodesExpected)
8724 return buildUnionOf2DMeshQuadratic(skin,n2o);
8726 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8730 * This method makes the assumption spacedimension == meshdimension == 3.
8731 * This method works only for linear cells.
8733 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8735 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8737 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8738 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8739 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8740 const int *conn=m->getNodalConnectivity()->getConstPointer();
8741 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8742 int nbOfCells=m->getNumberOfCells();
8743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8744 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8747 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8748 for(int i=1;i<nbOfCells;i++)
8751 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8757 * \brief Creates a graph of cell neighbors
8758 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8759 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8761 * - index: 0 3 5 6 6
8762 * - value: 1 2 3 2 3 3
8763 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8764 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8766 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8768 checkConnectivityFullyDefined();
8770 int meshDim = this->getMeshDimension();
8771 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8772 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8773 this->getReverseNodalConnectivity(revConn,indexr);
8774 const int* indexr_ptr=indexr->getConstPointer();
8775 const int* revConn_ptr=revConn->getConstPointer();
8777 const ParaMEDMEM::DataArrayInt* index;
8778 const ParaMEDMEM::DataArrayInt* conn;
8779 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8780 index=this->getNodalConnectivityIndex();
8781 int nbCells=this->getNumberOfCells();
8782 const int* index_ptr=index->getConstPointer();
8783 const int* conn_ptr=conn->getConstPointer();
8785 //creating graph arcs (cell to cell relations)
8786 //arcs are stored in terms of (index,value) notation
8789 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8790 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8792 //warning here one node have less than or equal effective number of cell with it
8793 //but cell could have more than effective nodes
8794 //because other equals nodes in other domain (with other global inode)
8795 std::vector <int> cell2cell_index(nbCells+1,0);
8796 std::vector <int> cell2cell;
8797 cell2cell.reserve(3*nbCells);
8799 for (int icell=0; icell<nbCells;icell++)
8801 std::map<int,int > counter;
8802 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8804 int inode=conn_ptr[iconn];
8805 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8807 int icell2=revConn_ptr[iconnr];
8808 std::map<int,int>::iterator iter=counter.find(icell2);
8809 if (iter!=counter.end()) (iter->second)++;
8810 else counter.insert(std::make_pair(icell2,1));
8813 for (std::map<int,int>::const_iterator iter=counter.begin();
8814 iter!=counter.end(); iter++)
8815 if (iter->second >= meshDim)
8817 cell2cell_index[icell+1]++;
8818 cell2cell.push_back(iter->first);
8823 cell2cell_index[0]=0;
8824 for (int icell=0; icell<nbCells;icell++)
8825 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8827 //filling up index and value to create skylinearray structure
8828 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8833 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8834 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8836 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8840 for(int i=0;i<nbOfNodesInCell;i++)
8841 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8842 else if(spaceDim==2)
8844 for(int i=0;i<nbOfNodesInCell;i++)
8846 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8851 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8854 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8856 int nbOfCells=getNumberOfCells();
8858 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8859 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};
8860 ofs << " <" << getVTKDataSetType() << ">\n";
8861 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8862 ofs << " <PointData>\n" << pointData << std::endl;
8863 ofs << " </PointData>\n";
8864 ofs << " <CellData>\n" << cellData << std::endl;
8865 ofs << " </CellData>\n";
8866 ofs << " <Points>\n";
8867 if(getSpaceDimension()==3)
8868 _coords->writeVTK(ofs,8,"Points",byteData);
8871 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8872 coo->writeVTK(ofs,8,"Points",byteData);
8874 ofs << " </Points>\n";
8875 ofs << " <Cells>\n";
8876 const int *cPtr=_nodal_connec->getConstPointer();
8877 const int *cIPtr=_nodal_connec_index->getConstPointer();
8878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8882 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8883 int szFaceOffsets=0,szConn=0;
8884 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8887 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8890 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8891 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8895 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8896 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8897 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8898 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8899 w4=std::copy(c.begin(),c.end(),w4);
8902 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8903 types->writeVTK(ofs,8,"UInt8","types",byteData);
8904 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8905 if(szFaceOffsets!=0)
8906 {//presence of Polyhedra
8907 connectivity->reAlloc(szConn);
8908 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8910 w1=faces->getPointer();
8911 for(int i=0;i<nbOfCells;i++)
8912 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8914 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8916 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8917 for(int j=0;j<nbFaces;j++)
8919 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8920 *w1++=(int)std::distance(w6,w5);
8921 w1=std::copy(w6,w5,w1);
8925 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8927 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8928 ofs << " </Cells>\n";
8929 ofs << " </Piece>\n";
8930 ofs << " </" << getVTKDataSetType() << ">\n";
8933 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8935 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8937 { stream << " Not set !"; return ; }
8938 stream << " Mesh dimension : " << _mesh_dim << ".";
8942 { stream << " No coordinates set !"; return ; }
8943 if(!_coords->isAllocated())
8944 { stream << " Coordinates set but not allocated !"; return ; }
8945 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8946 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8947 if(!_nodal_connec_index)
8948 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8949 if(!_nodal_connec_index->isAllocated())
8950 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8951 int lgth=_nodal_connec_index->getNumberOfTuples();
8952 int cpt=_nodal_connec_index->getNumberOfComponents();
8953 if(cpt!=1 || lgth<1)
8955 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8958 std::string MEDCouplingUMesh::getVTKDataSetType() const
8960 return std::string("UnstructuredGrid");
8963 std::string MEDCouplingUMesh::getVTKFileExtension() const
8965 return std::string("vtu");
8969 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8970 * returns a result mesh constituted by polygons.
8971 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8972 * all nodes from m2.
8973 * The meshes should be in 2D space. In
8974 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8976 * \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
8977 * 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)
8978 * \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
8979 * 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)
8980 * \param [in] eps - precision used to detect coincident mesh entities.
8981 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8982 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8983 * this array using decrRef() as it is no more needed.
8984 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8985 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8986 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8987 * any cell of \a m2. The caller is to delete this array using decrRef() as
8988 * it is no more needed.
8989 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8990 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8991 * is no more needed.
8992 * \throw If the coordinates array is not set in any of the meshes.
8993 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8994 * \throw If any of the meshes is not a 2D mesh in 2D space.
8996 * \sa conformize2D, mergeNodes
8998 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8999 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9002 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9003 m1->checkFullyDefined();
9004 m2->checkFullyDefined();
9005 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9006 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
9008 // Step 1: compute all edge intersections (new nodes)
9009 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9010 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9011 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9012 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9013 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9014 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9015 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9016 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9018 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9020 // Step 2: re-order newly created nodes according to the ordering found in m2
9021 std::vector< std::vector<int> > intersectEdge2;
9022 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9023 subDiv2.clear(); dd5=0; dd6=0;
9026 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9027 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9028 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9029 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9031 // Step 4: Prepare final result:
9032 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9033 addCooDa->alloc((int)(addCoo.size())/2,2);
9034 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9035 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9036 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9037 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9038 std::vector<const DataArrayDouble *> coordss(4);
9039 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9040 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9041 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9042 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9043 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9044 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9045 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9046 ret->setConnectivity(conn,connI,true);
9047 ret->setCoords(coo);
9048 cellNb1=c1.retn(); cellNb2=c2.retn();
9054 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9056 if(candidates.empty())
9058 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9060 const std::vector<int>& pool(intersectEdge1[*it]);
9061 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9062 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9067 tmp[0]=stop; tmp[1]=start;
9068 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9077 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,
9078 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9080 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9081 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9082 int nCells(mesh1D->getNumberOfCells());
9083 if(nCells!=(int)intersectEdge2.size())
9084 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9085 const DataArrayDouble *coo2(mesh1D->getCoords());
9086 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9087 const double *coo2Ptr(coo2->begin());
9088 int offset1(coords1->getNumberOfTuples());
9089 int offset2(offset1+coo2->getNumberOfTuples());
9090 int offset3(offset2+addCoo.size()/2);
9091 std::vector<double> addCooQuad;
9092 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9093 int tmp[4],cicnt(0),kk(0);
9094 for(int i=0;i<nCells;i++)
9096 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9097 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9098 const std::vector<int>& subEdges(intersectEdge2[i]);
9099 int nbSubEdge(subEdges.size()/2);
9100 for(int j=0;j<nbSubEdge;j++,kk++)
9102 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));
9103 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9104 INTERP_KERNEL::Edge *e2Ptr(e2);
9105 std::map<int,int>::const_iterator itm;
9106 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9108 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9109 itm=mergedNodes.find(subEdges[2*j]);
9110 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9111 itm=mergedNodes.find(subEdges[2*j+1]);
9112 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9113 tmp[3]=offset3+(int)addCooQuad.size()/2;
9115 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9117 cOut->insertAtTheEnd(tmp,tmp+4);
9118 ciOut->pushBackSilent(cicnt);
9122 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9123 itm=mergedNodes.find(subEdges[2*j]);
9124 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9125 itm=mergedNodes.find(subEdges[2*j+1]);
9126 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9128 cOut->insertAtTheEnd(tmp,tmp+3);
9129 ciOut->pushBackSilent(cicnt);
9132 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9134 idsInRetColinear->pushBackSilent(kk);
9135 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9140 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9141 ret->setConnectivity(cOut,ciOut,true);
9142 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9143 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9144 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9145 std::vector<const DataArrayDouble *> coordss(4);
9146 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9147 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9148 ret->setCoords(arr);
9152 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9154 std::vector<int> allEdges;
9155 for(const int *it2(descBg);it2!=descEnd;it2++)
9157 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9159 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9161 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9163 std::size_t nb(allEdges.size());
9165 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9166 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9167 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9168 ret->setCoords(coords);
9169 ret->allocateCells(1);
9170 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9171 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9172 connOut[kk]=allEdges[2*kk];
9173 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9177 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9179 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9180 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9182 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9183 if(sz!=std::distance(descBg,descEnd))
9184 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9185 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9186 std::vector<int> allEdges,centers;
9187 const double *coordsPtr(coords->begin());
9188 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9189 int offset(coords->getNumberOfTuples());
9190 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9192 INTERP_KERNEL::NormalizedCellType typeOfSon;
9193 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9194 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9196 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9198 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9200 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9202 {//the current edge has been subsplit -> create corresponding centers.
9203 std::size_t nbOfCentersToAppend(edge1.size()/2);
9204 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9205 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9206 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9207 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9210 const double *aa(coordsPtr+2*(*it3++));
9211 const double *bb(coordsPtr+2*(*it3++));
9212 ee->getMiddleOfPoints(aa,bb,tmpp);
9213 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9214 centers.push_back(offset+k);
9218 std::size_t nb(allEdges.size());
9220 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9221 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9222 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9224 ret->setCoords(coords);
9227 addCoo->rearrange(2);
9228 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9229 ret->setCoords(addCoo);
9231 ret->allocateCells(1);
9232 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9233 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9234 connOut[kk]=allEdges[2*kk];
9235 connOut.insert(connOut.end(),centers.begin(),centers.end());
9236 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9241 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9244 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9246 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9248 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9249 if(!cm.isQuadratic())
9250 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9252 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9255 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9258 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9260 const INTERP_KERNEL::Edge *ee(*it);
9261 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9265 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9268 const double *coo(mesh2D->getCoords()->begin());
9269 std::size_t sz(conn.size());
9270 std::vector<double> addCoo;
9271 std::vector<int> conn2(conn);
9272 int offset(mesh2D->getNumberOfNodes());
9273 for(std::size_t i=0;i<sz;i++)
9276 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9277 addCoo.insert(addCoo.end(),tmp,tmp+2);
9278 conn2.push_back(offset+(int)i);
9280 mesh2D->getCoords()->rearrange(1);
9281 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9282 mesh2D->getCoords()->rearrange(2);
9283 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9288 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9290 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9291 * a set of edges defined in \a splitMesh1D.
9293 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9294 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9296 std::size_t nb(edge1Bis.size()/2);
9297 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9298 int iEnd(splitMesh1D->getNumberOfCells());
9300 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9302 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9303 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9304 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9307 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9308 out0.resize(1); out1.resize(1);
9309 std::vector<int>& connOut(out0[0]);
9310 connOut.resize(nbOfEdgesOf2DCellSplit);
9311 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9312 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9313 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9315 connOut[kk]=edge1Bis[2*kk];
9316 edgesPtr[kk]=edge1BisPtr[2*kk];
9321 // [i,iEnd[ contains the
9322 out0.resize(2); out1.resize(2);
9323 std::vector<int>& connOutLeft(out0[0]);
9324 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9325 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9326 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9327 for(std::size_t k=ii;k<jj+1;k++)
9328 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9329 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9330 for(int ik=0;ik<iEnd;ik++)
9332 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9333 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9336 for(int ik=iEnd-1;ik>=0;ik--)
9337 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9338 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9339 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9340 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9341 for(int ik=0;ik<iEnd;ik++)
9342 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9343 eright.insert(eright.end(),ees.begin(),ees.end());
9355 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9357 std::vector<int> _edges;
9358 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9361 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9363 std::size_t nbe(edges.size());
9364 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9365 for(std::size_t i=0;i<nbe;i++)
9367 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9368 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9370 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9371 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9372 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9378 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9379 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9380 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9381 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9382 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9386 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9387 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9392 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9394 const MEDCouplingUMesh *mesh(_mesh);
9400 { _left++; _right++; return ; }
9403 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9404 if((isLeft && isRight) || (!isLeft && !isRight))
9405 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9416 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9417 if((isLeft && isRight) || (!isLeft && !isRight))
9418 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9433 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9435 const MEDCouplingUMesh *mesh(_mesh);
9438 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9441 {// not fully splitting cell case
9442 if(mesh2D->getNumberOfCells()==1)
9443 {//little optimization. 1 cell no need to find in which cell mesh is !
9444 neighbors[0]=offset; neighbors[1]=offset;
9449 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9450 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9452 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9453 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9458 class VectorOfCellInfo
9461 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9462 std::size_t size() const { return _pool.size(); }
9463 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9464 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);
9465 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9466 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9467 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9468 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9470 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9471 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9472 const CellInfo& get(int pos) const;
9473 CellInfo& get(int pos);
9475 std::vector<CellInfo> _pool;
9476 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9477 std::vector<EdgeInfo> _edge_info;
9480 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9482 _pool[0]._edges=edges;
9483 _pool[0]._edges_ptr=edgesPtr;
9486 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9489 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9492 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9494 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9495 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9496 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9499 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)
9501 get(pos);//to check pos
9502 bool isFast(pos==0 && _pool.size()==1);
9503 std::size_t sz(edges.size());
9504 // dealing with edges
9506 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9508 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9510 std::vector<CellInfo> pool(_pool.size()-1+sz);
9511 for(int i=0;i<pos;i++)
9513 for(std::size_t j=0;j<sz;j++)
9514 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9515 for(int i=pos+1;i<(int)_pool.size();i++)
9516 pool[i+sz-1]=_pool[i];
9520 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9528 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9531 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9535 if(pos<_ze_mesh->getNumberOfCells()-1)
9537 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9540 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9541 for(std::size_t j=0;j<ms2.size();j++)
9543 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9546 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9548 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9551 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9554 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9556 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9558 if((*it).isInMyRange(pos))
9561 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9564 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9566 get(pos);//to check;
9567 if(_edge_info.empty())
9569 std::size_t sz(_edge_info.size()-1);
9570 for(std::size_t i=0;i<sz;i++)
9571 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9574 const CellInfo& VectorOfCellInfo::get(int pos) const
9576 if(pos<0 || pos>=(int)_pool.size())
9577 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9581 CellInfo& VectorOfCellInfo::get(int pos)
9583 if(pos<0 || pos>=(int)_pool.size())
9584 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9590 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9591 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9593 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9595 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9597 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9599 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9602 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9603 if(nbCellsInSplitMesh1D==0)
9604 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9605 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9606 std::size_t nb(allEdges.size()),jj;
9608 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9609 std::vector<int> edge1Bis(nb*2);
9610 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9611 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9612 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9613 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9614 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9616 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9617 int *idsLeftRightPtr(idsLeftRight->getPointer());
9618 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9619 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9620 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9622 for(;iEnd<nbCellsInSplitMesh1D;)
9624 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9630 if(iEnd<nbCellsInSplitMesh1D)
9633 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9634 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9636 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9637 retTmp->setCoords(splitMesh1D->getCoords());
9638 retTmp->allocateCells();
9640 std::vector< std::vector<int> > out0;
9641 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9643 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9644 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9645 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9646 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9650 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9651 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9652 return pool.getZeMesh().retn();
9655 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9656 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9659 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9661 std::vector<int> allEdges;
9662 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9663 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9665 int edgeId(std::abs(*it)-1);
9666 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9667 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9668 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9670 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9672 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9673 std::size_t sz(edge1.size());
9674 for(std::size_t cnt=0;cnt<sz;cnt++)
9675 allEdgesPtr.push_back(ee);
9678 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9681 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9683 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9684 {//easy case comparison not
9685 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9687 else if(typ1.isQuadratic() && typ2.isQuadratic())
9689 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9692 if(conn1[2]==conn2[2])
9694 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9695 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9699 {//only one is quadratic
9700 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9703 const double *a(0),*bb(0),*be(0);
9704 if(typ1.isQuadratic())
9706 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9710 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9712 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9713 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9719 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9720 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9722 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9724 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9726 if(candidatesIn2DEnd==candidatesIn2DBg)
9727 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9728 const double *coo(mesh2DSplit->getCoords()->begin());
9729 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9730 return *candidatesIn2DBg;
9731 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9732 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9733 if(cellIdInMesh1DSplitRelative<0)
9734 cur1D->changeOrientationOfCells();
9735 const int *c1D(cur1D->getNodalConnectivity()->begin());
9736 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9737 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9739 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9740 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9741 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9742 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9743 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9744 for(unsigned it2=0;it2<sz;it2++)
9746 INTERP_KERNEL::NormalizedCellType typeOfSon;
9747 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9748 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9749 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9753 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9759 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9760 * 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
9761 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9762 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9764 * \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
9765 * 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)
9766 * \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
9767 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9768 * \param [in] eps - precision used to perform intersections and localization operations.
9769 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9770 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9771 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9772 * 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.
9773 * \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
9774 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9775 * 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.
9777 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9779 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9781 if(!mesh2D || !mesh1D)
9782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9783 mesh2D->checkFullyDefined();
9784 mesh1D->checkFullyDefined();
9785 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9786 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9787 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9788 // Step 1: compute all edge intersections (new nodes)
9789 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9790 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9791 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9792 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9794 // Build desc connectivity
9795 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9797 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9798 std::map<int,int> mergedNodes;
9799 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9800 // use mergeNodes to fix intersectEdge1
9801 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9803 std::size_t n((*it0).size()/2);
9804 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9805 std::map<int,int>::const_iterator it1;
9806 it1=mergedNodes.find(eltStart);
9807 if(it1!=mergedNodes.end())
9808 (*it0)[0]=(*it1).second;
9809 it1=mergedNodes.find(eltEnd);
9810 if(it1!=mergedNodes.end())
9811 (*it0)[2*n-1]=(*it1).second;
9814 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9815 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9816 // Step 2: re-order newly created nodes according to the ordering found in m2
9817 std::vector< std::vector<int> > intersectEdge2;
9818 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9820 // Step 3: compute splitMesh1D
9821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9823 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9824 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9825 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9827 // deal with cells in mesh2D that are not cut but only some of their edges are
9828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9829 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9830 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9831 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
9832 if(!idsInDesc2DToBeRefined->empty())
9834 DataArrayInt *out0(0),*outi0(0);
9835 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9838 out0s=out0s->buildUnique();
9842 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9843 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9845 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9847 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9848 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9849 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9851 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9852 if((DataArrayInt *)out0s)
9853 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9854 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9855 // OK all is ready to insert in ret2 mesh
9856 if(!untouchedCells->empty())
9857 {// the most easy part, cells in mesh2D not impacted at all
9858 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9859 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9860 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9862 if((DataArrayInt *)out0s)
9863 {// here dealing with cells in out0s but not in cellsToBeModified
9864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9865 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9866 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9868 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9869 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9871 int offset(ret2->getNumberOfTuples());
9872 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9874 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9875 int kk(0),*ret3ptr(partOfRet3->getPointer());
9876 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9878 int faceId(std::abs(*it)-1);
9879 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9881 int tmp(fewModifiedCells->locateValue(*it2));
9884 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9885 ret3ptr[2*kk]=tmp+offset;
9886 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9887 ret3ptr[2*kk+1]=tmp+offset;
9890 {//the current edge is shared by a 2D cell that will be split just after
9891 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9892 ret3ptr[2*kk]=-(*it2+1);
9893 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9894 ret3ptr[2*kk+1]=-(*it2+1);
9898 m1Desc->setCoords(ret1->getCoords());
9899 ret1NonCol->setCoords(ret1->getCoords());
9900 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9901 if(!outMesh2DSplit.empty())
9903 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9904 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9905 (*itt)->setCoords(da);
9908 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9909 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9912 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9914 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9916 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));
9917 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9918 outMesh2DSplit.push_back(splitOfOneCell);
9919 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9920 ret2->pushBackSilent(*it);
9923 std::size_t nbOfMeshes(outMesh2DSplit.size());
9924 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9925 for(std::size_t i=0;i<nbOfMeshes;i++)
9926 tmp[i]=outMesh2DSplit[i];
9928 ret1->getCoords()->setInfoOnComponents(compNames);
9929 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9930 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9933 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9935 int old2DCellId(-ret3->getIJ(*it,0)-1);
9936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9937 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
9939 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9942 splitMesh1D=ret1.retn();
9943 splitMesh2D=ret2D.retn();
9944 cellIdInMesh2D=ret2.retn();
9945 cellIdInMesh1D=ret3.retn();
9949 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9950 * (newly created) nodes corresponding to the edge intersections.
9952 * @param[out] cr, crI connectivity of the resulting mesh
9953 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9954 * TODO: describe input parameters
9956 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9957 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9958 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9959 const std::vector<double>& addCoords,
9960 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9962 static const int SPACEDIM=2;
9963 const double *coo1(m1->getCoords()->getConstPointer());
9964 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9965 int offset1(m1->getNumberOfNodes());
9966 const double *coo2(m2->getCoords()->getConstPointer());
9967 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9968 int offset2(offset1+m2->getNumberOfNodes());
9969 int offset3(offset2+((int)addCoords.size())/2);
9970 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9971 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9972 // Here a BBTree on 2D-cells, not on segments:
9973 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9974 int ncell1(m1->getNumberOfCells());
9976 for(int i=0;i<ncell1;i++)
9978 std::vector<int> candidates2;
9979 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9980 std::map<INTERP_KERNEL::Node *,int> mapp;
9981 std::map<int,INTERP_KERNEL::Node *> mappRev;
9982 INTERP_KERNEL::QuadraticPolygon pol1;
9983 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9984 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9985 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9986 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9987 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9988 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9989 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9991 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
9992 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9993 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9994 for(it1.first();!it1.finished();it1.next())
9995 edges1.insert(it1.current()->getPtr());
9997 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9998 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10000 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10002 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10003 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10004 // Complete mapping with elements coming from the current cell it2 in mesh2:
10005 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10006 // pol2 is the new QP in the final merged result.
10007 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10008 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10011 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10013 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10014 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10015 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10016 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10018 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10019 // by m2 but that we still want to keep in the final result.
10020 if(!edges1.empty())
10024 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10026 catch(INTERP_KERNEL::Exception& e)
10028 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();
10029 throw INTERP_KERNEL::Exception(oss.str().c_str());
10032 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10033 (*it).second->decrRef();
10038 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10039 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10040 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10041 * The caller is to deal with the resulting DataArrayInt.
10042 * \throw If the coordinate array is not set.
10043 * \throw If the nodal connectivity of the cells is not defined.
10044 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10045 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10047 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10049 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10051 checkFullyDefined();
10052 if(getMeshDimension()!=1)
10053 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10055 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10058 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10059 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10060 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10062 const int * dsi(_dsi->getConstPointer());
10063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10065 if (dsii->getNumberOfTuples())
10066 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10068 int nc(getNumberOfCells());
10069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10070 result->alloc(nc,1);
10072 // set of edges not used so far
10073 std::set<int> edgeSet;
10074 for (int i=0; i<nc; edgeSet.insert(i), i++);
10078 // while we have points with only one neighbor segments
10081 std::list<int> linePiece;
10082 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10083 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10085 // Fill the list forward (resp. backward) from the start segment:
10086 int activeSeg = startSeg;
10087 int prevPointId = -20;
10089 while (!edgeSet.empty())
10091 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10094 linePiece.push_back(activeSeg);
10096 linePiece.push_front(activeSeg);
10097 edgeSet.erase(activeSeg);
10100 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10101 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10102 if (dsi[ptId] == 1) // hitting the end of the line
10104 prevPointId = ptId;
10105 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10106 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10109 // Done, save final piece into DA:
10110 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10111 newIdx += linePiece.size();
10113 // identify next valid start segment (one which is not consumed)
10114 if(!edgeSet.empty())
10115 startSeg = *(edgeSet.begin());
10117 while (!edgeSet.empty());
10118 return result.retn();
10123 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10125 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10126 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10128 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10129 int v((*it).second);
10130 if(v==forbVal0 || v==forbVal1)
10132 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10133 isect.push_back(v);
10136 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10141 bool presenceOfOn(false);
10142 for(int i=0;i<sz;i++)
10144 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10145 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10147 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10148 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10150 return presenceOfOn;
10156 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10157 * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10158 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10159 * a minimal creation of new nodes is wanted.
10160 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10161 * nodes if a SEG3 is split without information of middle.
10162 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10163 * avoid to have a non conform mesh.
10165 * \return int - the number of new nodes created (in most of cases 0).
10167 * \throw If \a this is not coherent.
10168 * \throw If \a this has not spaceDim equal to 2.
10169 * \throw If \a this has not meshDim equal to 2.
10170 * \throw If some subcells needed to be split are orphan.
10171 * \sa MEDCouplingUMesh::conformize2D
10173 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10175 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10176 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10177 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10178 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10179 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10180 if(midOpt==0 && midOptI==0)
10182 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10185 else if(midOpt!=0 && midOptI!=0)
10186 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10188 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10192 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10193 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10194 * 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
10195 * 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).
10196 * 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.
10198 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10199 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10201 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10202 * This method expects that all nodes in \a this are not closer than \a eps.
10203 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10205 * \param [in] eps the relative error to detect merged edges.
10206 * \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
10207 * that the user is expected to deal with.
10209 * \throw If \a this is not coherent.
10210 * \throw If \a this has not spaceDim equal to 2.
10211 * \throw If \a this has not meshDim equal to 2.
10212 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10214 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10216 static const int SPACEDIM=2;
10218 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10219 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10221 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10222 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10223 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10224 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10225 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10226 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10227 std::vector<double> addCoo;
10228 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10229 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10230 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10231 for(int i=0;i<nDescCell;i++)
10233 std::vector<int> candidates;
10234 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10235 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10238 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10239 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10240 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10241 INTERP_KERNEL::MergePoints merge;
10242 INTERP_KERNEL::QuadraticPolygon c1,c2;
10243 e1->intersectWith(e2,merge,c1,c2);
10244 e1->decrRef(); e2->decrRef();
10245 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10246 overlapEdge[i].push_back(*it);
10247 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10248 overlapEdge[*it].push_back(i);
10251 // splitting done. sort intersect point in intersectEdge.
10252 std::vector< std::vector<int> > middle(nDescCell);
10253 int nbOf2DCellsToBeSplit(0);
10254 bool middleNeedsToBeUsed(false);
10255 std::vector<bool> cells2DToTreat(nDescCell,false);
10256 for(int i=0;i<nDescCell;i++)
10258 std::vector<int>& isect(intersectEdge[i]);
10259 int sz((int)isect.size());
10262 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10263 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10264 e->sortSubNodesAbs(coords,isect);
10269 int idx0(rdi[i]),idx1(rdi[i+1]);
10271 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10272 if(!cells2DToTreat[rd[idx0]])
10274 cells2DToTreat[rd[idx0]]=true;
10275 nbOf2DCellsToBeSplit++;
10277 // try to reuse at most eventual 'middle' of SEG3
10278 std::vector<int>& mid(middle[i]);
10279 mid.resize(sz+1,-1);
10280 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10282 middleNeedsToBeUsed=true;
10283 const std::vector<int>& candidates(overlapEdge[i]);
10284 std::vector<int> trueCandidates;
10285 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10286 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10287 trueCandidates.push_back(*itc);
10288 int stNode(c[ci[i]+1]),endNode(isect[0]);
10289 for(int j=0;j<sz+1;j++)
10291 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10293 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10294 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10295 { mid[j]=*itc; break; }
10298 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10303 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10304 if(nbOf2DCellsToBeSplit==0)
10307 int *retPtr(ret->getPointer());
10308 for(int i=0;i<nCell;i++)
10309 if(cells2DToTreat[i])
10312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10313 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10314 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10315 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10316 if(middleNeedsToBeUsed)
10317 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10318 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10319 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10320 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.
10321 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10323 bool areNodesMerged; int newNbOfNodes;
10324 if(nbOfNodesCreated!=0)
10325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10331 * 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.
10332 * 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).
10333 * 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
10334 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10335 * 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
10336 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10338 * 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
10339 * using new instance, idem for coordinates.
10341 * 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.
10343 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10345 * \throw If \a this is not coherent.
10346 * \throw If \a this has not spaceDim equal to 2.
10347 * \throw If \a this has not meshDim equal to 2.
10349 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10351 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10355 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10356 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10357 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10358 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10359 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10360 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10362 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10363 const double *coords(_coords->begin());
10364 int *newciptr(newci->getPointer());
10365 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10367 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10368 ret->pushBackSilent(i);
10369 newciptr[1]=newc->getNumberOfTuples();
10374 if(!appendedCoords->empty())
10376 appendedCoords->rearrange(2);
10377 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10379 setCoords(newCoords);
10382 setConnectivity(newc,newci,true);
10387 * \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.
10388 * 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.
10389 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10390 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10391 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10392 * \param [out] addCoo - nodes to be append at the end
10393 * \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.
10395 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10396 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)
10398 static const int SPACEDIM=2;
10399 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10400 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10401 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10402 // Build BB tree of all edges in the tool mesh (second mesh)
10403 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10404 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10405 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10406 intersectEdge1.resize(nDescCell1);
10407 colinear2.resize(nDescCell2);
10408 subDiv2.resize(nDescCell2);
10409 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10411 std::vector<int> candidates1(1);
10412 int offset1(m1Desc->getNumberOfNodes());
10413 int offset2(offset1+m2Desc->getNumberOfNodes());
10414 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10416 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10417 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10418 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10420 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10421 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10422 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10424 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10425 // 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
10426 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10427 std::set<INTERP_KERNEL::Node *> nodes;
10428 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10429 std::size_t szz(nodes.size());
10430 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10431 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10432 for(std::size_t iii=0;iii<szz;iii++,itt++)
10433 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10434 // end of protection
10435 // Performs egde cutting:
10436 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10441 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10442 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10447 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10448 * It builds the descending connectivity of the two meshes, and then using a binary tree
10449 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10450 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10452 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10453 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10454 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10455 std::vector<double>& addCoo,
10456 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10458 // Build desc connectivity
10459 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10460 desc2=DataArrayInt::New();
10461 descIndx2=DataArrayInt::New();
10462 revDesc2=DataArrayInt::New();
10463 revDescIndx2=DataArrayInt::New();
10464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10466 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10467 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10468 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10469 std::map<int,int> notUsedMap;
10470 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10471 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10472 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10476 * This method performs the 2nd step of Partition of 2D mesh.
10477 * This method has 4 inputs :
10478 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10479 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10480 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10481 * 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'
10482 * Nodes end up lying consecutively on a cutted edge.
10483 * \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.
10484 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10485 * \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.
10486 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10487 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10489 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10490 const std::vector<double>& addCoo,
10491 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10493 int offset1=m1->getNumberOfNodes();
10494 int ncell=m2->getNumberOfCells();
10495 const int *c=m2->getNodalConnectivity()->getConstPointer();
10496 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10497 const double *coo=m2->getCoords()->getConstPointer();
10498 const double *cooBis=m1->getCoords()->getConstPointer();
10499 int offset2=offset1+m2->getNumberOfNodes();
10500 intersectEdge.resize(ncell);
10501 for(int i=0;i<ncell;i++,cI++)
10503 const std::vector<int>& divs=subDiv[i];
10504 int nnode=cI[1]-cI[0]-1;
10505 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10506 std::map<INTERP_KERNEL::Node *, int> mapp22;
10507 for(int j=0;j<nnode;j++)
10509 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10510 int nnid=c[(*cI)+j+1];
10511 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10512 mapp22[nn]=nnid+offset1;
10514 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10515 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10516 ((*it).second.first)->decrRef();
10517 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10518 std::map<INTERP_KERNEL::Node *,int> mapp3;
10519 for(std::size_t j=0;j<divs.size();j++)
10522 INTERP_KERNEL::Node *tmp=0;
10524 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10525 else if(id<offset2)
10526 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10528 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10532 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10533 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10540 * 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).
10541 * 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
10542 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10543 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10544 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10545 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10546 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10547 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10548 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10549 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10550 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10551 * \param [out] cut3DSuf input/output param.
10553 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10554 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10555 const int *desc, const int *descIndx,
10556 std::vector< std::pair<int,int> >& cut3DSurf)
10558 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10559 int nbOf3DSurfCell=(int)cut3DSurf.size();
10560 for(int i=0;i<nbOf3DSurfCell;i++)
10562 std::vector<int> res;
10563 int offset=descIndx[i];
10564 int nbOfSeg=descIndx[i+1]-offset;
10565 for(int j=0;j<nbOfSeg;j++)
10567 int edgeId=desc[offset+j];
10568 int status=cut3DCurve[edgeId];
10572 res.push_back(status);
10575 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10576 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10584 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10590 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10591 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10594 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10598 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10603 {// case when plane is on a multi colinear edge of a polyhedron
10604 if((int)res.size()==2*nbOfSeg)
10606 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10609 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10616 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10617 * 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).
10618 * 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
10619 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10620 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10621 * \param desc is the descending connectivity 3D->3DSurf
10622 * \param descIndx is the descending connectivity index 3D->3DSurf
10624 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10625 const int *desc, const int *descIndx,
10626 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10628 checkFullyDefined();
10629 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10631 const int *nodal3D=_nodal_connec->getConstPointer();
10632 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10633 int nbOfCells=getNumberOfCells();
10634 for(int i=0;i<nbOfCells;i++)
10636 std::map<int, std::set<int> > m;
10637 int offset=descIndx[i];
10638 int nbOfFaces=descIndx[i+1]-offset;
10641 for(int j=0;j<nbOfFaces;j++)
10643 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10644 if(p.first!=-1 && p.second!=-1)
10648 start=p.first; end=p.second;
10649 m[p.first].insert(p.second);
10650 m[p.second].insert(p.first);
10654 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10655 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10656 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10657 INTERP_KERNEL::NormalizedCellType cmsId;
10658 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10659 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10660 for(unsigned k=0;k<nbOfNodesSon;k++)
10662 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10663 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10670 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10674 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10675 const std::set<int>& s=(*it).second;
10676 std::set<int> s2; s2.insert(prev);
10678 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10681 int val=*s3.begin();
10682 conn.push_back(start);
10689 conn.push_back(end);
10692 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10693 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10694 cellIds->pushBackSilent(i);
10700 * 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
10701 * 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
10702 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10703 * 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
10704 * 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.
10706 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10708 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10710 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10713 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10714 if(cm.getDimension()==2)
10716 const int *node=nodalConnBg+1;
10717 int startNode=*node++;
10718 double refX=coords[2*startNode];
10719 for(;node!=nodalConnEnd;node++)
10721 if(coords[2*(*node)]<refX)
10724 refX=coords[2*startNode];
10727 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10731 double angle0=-M_PI/2;
10736 double angleNext=0.;
10737 while(nextNode!=startNode)
10741 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10743 if(*node!=tmpOut.back() && *node!=prevNode)
10745 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10746 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10751 res=angle0-angleM+2.*M_PI;
10760 if(nextNode!=startNode)
10762 angle0=angleNext-M_PI;
10765 prevNode=tmpOut.back();
10766 tmpOut.push_back(nextNode);
10769 std::vector<int> tmp3(2*(sz-1));
10770 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10771 std::copy(nodalConnBg+1,nodalConnEnd,it);
10772 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10774 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10777 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10779 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10784 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10785 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10793 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10797 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10798 * 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.
10800 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10801 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10802 * \param [in,out] arr array in which the remove operation will be done.
10803 * \param [in,out] arrIndx array in the remove operation will modify
10804 * \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])
10805 * \return true if \b arr and \b arrIndx have been modified, false if not.
10807 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10809 if(!arrIndx || !arr)
10810 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10811 if(offsetForRemoval<0)
10812 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10813 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10814 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10815 int *arrIPtr=arrIndx->getPointer();
10817 int previousArrI=0;
10818 const int *arrPtr=arr->getConstPointer();
10819 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10820 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10822 if(*arrIPtr-previousArrI>offsetForRemoval)
10824 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10826 if(s.find(*work)==s.end())
10827 arrOut.push_back(*work);
10830 previousArrI=*arrIPtr;
10831 *arrIPtr=(int)arrOut.size();
10833 if(arr->getNumberOfTuples()==(int)arrOut.size())
10835 arr->alloc((int)arrOut.size(),1);
10836 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10841 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10842 * (\ref numbering-indirect).
10843 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10844 * The selection of extraction is done standardly in new2old format.
10845 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10847 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10848 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10849 * \param [in] arrIn arr origin array from which the extraction will be done.
10850 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10851 * \param [out] arrOut the resulting array
10852 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10853 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10855 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10856 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10858 if(!arrIn || !arrIndxIn)
10859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10860 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10861 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10862 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10863 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10864 const int *arrInPtr=arrIn->getConstPointer();
10865 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10866 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10869 int maxSizeOfArr=arrIn->getNumberOfTuples();
10870 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10872 arrIo->alloc((int)(sz+1),1);
10873 const int *idsIt=idsOfSelectBg;
10874 int *work=arrIo->getPointer();
10877 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10879 if(*idsIt>=0 && *idsIt<nbOfGrps)
10880 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10883 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10884 throw INTERP_KERNEL::Exception(oss.str().c_str());
10890 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10891 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10892 throw INTERP_KERNEL::Exception(oss.str().c_str());
10895 arro->alloc(lgth,1);
10896 work=arro->getPointer();
10897 idsIt=idsOfSelectBg;
10898 for(std::size_t i=0;i<sz;i++,idsIt++)
10900 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10901 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10904 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10905 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10906 throw INTERP_KERNEL::Exception(oss.str().c_str());
10909 arrOut=arro.retn();
10910 arrIndexOut=arrIo.retn();
10914 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10915 * (\ref numbering-indirect).
10916 * 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 ).
10917 * The selection of extraction is done standardly in new2old format.
10918 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10920 * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10921 * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10922 * \param [in] idsOfSelectStep
10923 * \param [in] arrIn arr origin array from which the extraction will be done.
10924 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10925 * \param [out] arrOut the resulting array
10926 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10927 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10929 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10930 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10932 if(!arrIn || !arrIndxIn)
10933 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10934 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10935 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10937 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10938 const int *arrInPtr=arrIn->getConstPointer();
10939 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10940 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10942 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10943 int maxSizeOfArr=arrIn->getNumberOfTuples();
10944 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10945 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10946 arrIo->alloc((int)(sz+1),1);
10947 int idsIt=idsOfSelectStart;
10948 int *work=arrIo->getPointer();
10951 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10953 if(idsIt>=0 && idsIt<nbOfGrps)
10954 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10957 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10958 throw INTERP_KERNEL::Exception(oss.str().c_str());
10964 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10965 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10966 throw INTERP_KERNEL::Exception(oss.str().c_str());
10969 arro->alloc(lgth,1);
10970 work=arro->getPointer();
10971 idsIt=idsOfSelectStart;
10972 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10974 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10975 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10978 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10979 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10980 throw INTERP_KERNEL::Exception(oss.str().c_str());
10983 arrOut=arro.retn();
10984 arrIndexOut=arrIo.retn();
10988 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10989 * 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
10990 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10991 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10993 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10994 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10995 * \param [in] arrIn arr origin array from which the extraction will be done.
10996 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10997 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10998 * \param [in] srcArrIndex index array of \b srcArr
10999 * \param [out] arrOut the resulting array
11000 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11002 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11004 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11005 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11006 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11008 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11009 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11012 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11013 std::vector<bool> v(nbOfTuples,true);
11015 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11016 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11017 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11019 if(*it>=0 && *it<nbOfTuples)
11022 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11026 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11027 throw INTERP_KERNEL::Exception(oss.str().c_str());
11030 srcArrIndexPtr=srcArrIndex->getConstPointer();
11031 arrIo->alloc(nbOfTuples+1,1);
11032 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11033 const int *arrInPtr=arrIn->getConstPointer();
11034 const int *srcArrPtr=srcArr->getConstPointer();
11035 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11036 int *arroPtr=arro->getPointer();
11037 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11041 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11042 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11046 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11047 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11048 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11051 arrOut=arro.retn();
11052 arrIndexOut=arrIo.retn();
11056 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11057 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11059 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11060 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11061 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11062 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11063 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11064 * \param [in] srcArrIndex index array of \b srcArr
11066 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11068 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11069 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11071 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11072 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11073 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11074 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11075 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11076 int *arrInOutPtr=arrInOut->getPointer();
11077 const int *srcArrPtr=srcArr->getConstPointer();
11078 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11080 if(*it>=0 && *it<nbOfTuples)
11082 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11083 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11086 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] !";
11087 throw INTERP_KERNEL::Exception(oss.str().c_str());
11092 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11093 throw INTERP_KERNEL::Exception(oss.str().c_str());
11099 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11100 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11101 * 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]].
11102 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11103 * A negative value in \b arrIn means that it is ignored.
11104 * 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.
11106 * \param [in] arrIn arr origin array from which the extraction will be done.
11107 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11108 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11109 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11111 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11113 int seed=0,nbOfDepthPeelingPerformed=0;
11114 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11118 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11119 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11120 * 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]].
11121 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11122 * A negative value in \b arrIn means that it is ignored.
11123 * 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.
11124 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11125 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11126 * \param [in] arrIn arr origin array from which the extraction will be done.
11127 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11128 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11129 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11130 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11131 * \sa MEDCouplingUMesh::partitionBySpreadZone
11133 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11135 nbOfDepthPeelingPerformed=0;
11137 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11138 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11141 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11145 std::vector<bool> fetched(nbOfTuples,false);
11146 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11149 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11151 nbOfDepthPeelingPerformed=0;
11152 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11154 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11155 std::vector<bool> fetched2(nbOfTuples,false);
11157 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11159 if(*seedElt>=0 && *seedElt<nbOfTuples)
11160 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11162 { 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()); }
11164 const int *arrInPtr=arrIn->getConstPointer();
11165 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11166 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11167 std::vector<int> idsToFetch1(seedBg,seedEnd);
11168 std::vector<int> idsToFetch2;
11169 std::vector<int> *idsToFetch=&idsToFetch1;
11170 std::vector<int> *idsToFetchOther=&idsToFetch2;
11171 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11173 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11174 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11176 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11177 std::swap(idsToFetch,idsToFetchOther);
11178 idsToFetchOther->clear();
11179 nbOfDepthPeelingPerformed++;
11181 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11184 int *retPtr=ret->getPointer();
11185 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11192 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11193 * 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
11194 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11195 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11197 * \param [in] start begin of set of ids of the input extraction (included)
11198 * \param [in] end end of set of ids of the input extraction (excluded)
11199 * \param [in] step step of the set of ids in range mode.
11200 * \param [in] arrIn arr origin array from which the extraction will be done.
11201 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11202 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11203 * \param [in] srcArrIndex index array of \b srcArr
11204 * \param [out] arrOut the resulting array
11205 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11207 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11209 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11210 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11211 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11213 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11214 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11217 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11219 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11220 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11221 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11223 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11225 if(it>=0 && it<nbOfTuples)
11226 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11229 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11230 throw INTERP_KERNEL::Exception(oss.str().c_str());
11233 srcArrIndexPtr=srcArrIndex->getConstPointer();
11234 arrIo->alloc(nbOfTuples+1,1);
11235 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11236 const int *arrInPtr=arrIn->getConstPointer();
11237 const int *srcArrPtr=srcArr->getConstPointer();
11238 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11239 int *arroPtr=arro->getPointer();
11240 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11242 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11245 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11246 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11250 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11251 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11254 arrOut=arro.retn();
11255 arrIndexOut=arrIo.retn();
11259 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11260 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11262 * \param [in] start begin of set of ids of the input extraction (included)
11263 * \param [in] end end of set of ids of the input extraction (excluded)
11264 * \param [in] step step of the set of ids in range mode.
11265 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11266 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11267 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11268 * \param [in] srcArrIndex index array of \b srcArr
11270 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11272 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11273 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11275 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11277 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11278 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11279 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11280 int *arrInOutPtr=arrInOut->getPointer();
11281 const int *srcArrPtr=srcArr->getConstPointer();
11282 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11284 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11286 if(it>=0 && it<nbOfTuples)
11288 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11289 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11292 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11293 throw INTERP_KERNEL::Exception(oss.str().c_str());
11298 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11299 throw INTERP_KERNEL::Exception(oss.str().c_str());
11305 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11306 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11307 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11308 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11309 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11311 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11313 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11315 checkFullyDefined();
11316 int mdim=getMeshDimension();
11317 int spaceDim=getSpaceDimension();
11319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11320 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11321 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11322 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11324 ret->setCoords(getCoords());
11325 ret->allocateCells((int)partition.size());
11327 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11329 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11334 cell=tmp->buildUnionOf2DMesh();
11337 cell=tmp->buildUnionOf3DMesh();
11340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11343 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11346 ret->finishInsertingCells();
11351 * This method partitions \b this into contiguous zone.
11352 * This method only needs a well defined connectivity. Coordinates are not considered here.
11353 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11355 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11357 int nbOfCellsCur=getNumberOfCells();
11358 std::vector<DataArrayInt *> ret;
11359 if(nbOfCellsCur<=0)
11361 DataArrayInt *neigh=0,*neighI=0;
11362 computeNeighborsOfCells(neigh,neighI);
11363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11364 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11365 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11367 while(seed<nbOfCellsCur)
11369 int nbOfPeelPerformed=0;
11370 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11371 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11373 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11374 ret.push_back((*it).retn());
11379 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11380 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11382 * \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.
11383 * \return a newly allocated DataArrayInt to be managed by the caller.
11384 * \throw In case of \a code has not the right format (typically of size 3*n)
11386 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11389 std::size_t nb=code.size()/3;
11390 if(code.size()%3!=0)
11391 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11392 ret->alloc((int)nb,2);
11393 int *retPtr=ret->getPointer();
11394 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11396 retPtr[0]=code[3*i+2];
11397 retPtr[1]=code[3*i+2]+code[3*i+1];
11403 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11404 * All cells in \a this are expected to be linear 3D cells.
11405 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11406 * It leads to an increase to number of cells.
11407 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11408 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11409 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11411 * \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.
11412 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11413 * \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.
11414 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11415 * an id of old cell producing it. The caller is to delete this array using
11416 * decrRef() as it is no more needed.
11417 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11419 * \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
11420 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11422 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11423 * \throw If \a this is not fully constituted with linear 3D cells.
11424 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11426 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11428 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11429 checkConnectivityFullyDefined();
11430 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11431 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11432 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11433 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11434 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11435 int *retPt(ret->getPointer());
11436 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11437 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11438 const int *oldc(_nodal_connec->begin());
11439 const int *oldci(_nodal_connec_index->begin());
11440 const double *coords(_coords->begin());
11441 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11443 std::vector<int> a; std::vector<double> b;
11444 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11445 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11446 const int *aa(&a[0]);
11449 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11451 *it=(-(*(it))-1+nbNodes);
11452 addPts->insertAtTheEnd(b.begin(),b.end());
11453 nbNodes+=(int)b.size()/3;
11455 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11456 newConn->insertAtTheEnd(aa,aa+4);
11458 if(!addPts->empty())
11460 addPts->rearrange(3);
11461 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11462 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11463 ret0->setCoords(addPts);
11467 nbOfAdditionalPoints=0;
11468 ret0->setCoords(getCoords());
11470 ret0->setNodalConnectivity(newConn);
11472 ret->computeOffsets2();
11473 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11474 return ret0.retn();
11478 * 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).
11480 * \sa MEDCouplingUMesh::split2DCells
11482 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11484 checkConnectivityFullyDefined();
11485 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11487 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11488 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11489 int prevPosOfCi(ciPtr[0]);
11490 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11492 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11493 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11494 for(int j=0;j<sz;j++)
11496 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11497 for(int k=0;k<sz2;k++)
11498 *cPtr++=subPtr[offset2+k];
11500 *cPtr++=oldConn[prevPosOfCi+j+2];
11503 prevPosOfCi=ciPtr[1];
11504 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11507 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11508 _nodal_connec->decrRef();
11509 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11512 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11518 int ret(nodesCnter++);
11520 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11521 addCoo.insertAtTheEnd(newPt,newPt+2);
11526 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11532 int ret(nodesCnter++);
11534 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11535 addCoo.insertAtTheEnd(newPt,newPt+2);
11543 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)
11546 int trueStart(start>=0?start:nbOfEdges+start);
11547 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11548 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11553 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11554 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11555 middles.push_back(tmp3+offset);
11558 middles.push_back(connBg[trueStart+nbOfEdges]);
11562 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)
11564 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11565 newConnOfCell->pushBackSilent(tmpEnd);
11570 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11571 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11572 middles.push_back(tmp3+offset);
11575 middles.push_back(connBg[start+nbOfEdges]);
11579 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)
11581 // only the quadratic point to deal with:
11586 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11587 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11588 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11589 middles.push_back(tmp3+offset);
11592 middles.push_back(connBg[start+nbOfEdges]);
11599 * 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 ) .
11600 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11602 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11604 std::size_t sz(std::distance(connBg,connEnd));
11605 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11606 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11608 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11609 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11610 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11611 unsigned nbOfHit(0); // number of fusions operated
11612 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11613 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
11614 INTERP_KERNEL::NormalizedCellType typeOfSon;
11615 std::vector<int> middles;
11617 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11619 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11620 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11621 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11622 posEndElt = posBaseElt+1;
11624 // Look backward first: are the final edges of the cells colinear with the first ones?
11625 // This initializes posBaseElt.
11628 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11630 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11631 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11632 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11633 bool isColinear=eint->areColinears();
11646 // Now move forward:
11647 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11648 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11650 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11651 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11652 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11653 bool isColinear(eint->areColinears());
11665 //push [posBaseElt,posEndElt) in newConnOfCell using e
11666 // 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!
11668 // at the begining of the connectivity (insert type)
11669 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11670 else if((nbOfHit+nbOfTurn) != (nbs-1))
11672 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11673 if ((nbOfHit+nbOfTurn) == (nbs-1))
11674 // at the end (only quad points to deal with)
11675 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11676 posBaseElt=posEndElt;
11679 if(!middles.empty())
11680 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11685 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11687 * \return int - the number of new nodes created.
11688 * \sa MEDCouplingUMesh::split2DCells
11690 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11693 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11695 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11696 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11697 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11698 const double *oldCoordsPtr(getCoords()->begin());
11699 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11700 int prevPosOfCi(ciPtr[0]);
11701 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11703 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11704 for(int j=0;j<sz;j++)
11705 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11706 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11707 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11709 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11713 cPtr[1]=oldConn[prevPosOfCi+2+j];
11714 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11717 std::vector<INTERP_KERNEL::Node *> ns(3);
11718 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11719 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11720 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11721 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11722 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11724 cPtr[1]=subPtr[offset2+k];
11725 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11727 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11729 { cPtr[1]=tmpEnd; }
11730 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11732 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11733 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11736 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11737 _nodal_connec->decrRef();
11738 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11739 addCoo->rearrange(2);
11740 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11742 return addCoo->getNumberOfTuples();
11745 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11747 if(nodalConnec && nodalConnecIndex)
11750 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11751 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11753 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11754 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11758 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11759 _own_cell(true),_cell_id(-1),_nb_cell(0)
11764 _nb_cell=mesh->getNumberOfCells();
11768 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11776 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11777 _own_cell(false),_cell_id(bg-1),
11784 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11787 if(_cell_id<_nb_cell)
11796 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11802 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11804 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11807 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11813 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11821 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11827 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11832 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11837 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11839 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11842 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11847 _nb_cell=mesh->getNumberOfCells();
11851 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11858 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11860 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11861 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11862 if(_cell_id<_nb_cell)
11864 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11865 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11866 int startId=_cell_id;
11867 _cell_id+=nbOfElems;
11868 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11874 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11878 _conn=mesh->getNodalConnectivity()->getPointer();
11879 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11883 void MEDCouplingUMeshCell::next()
11885 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11890 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11893 std::string MEDCouplingUMeshCell::repr() const
11895 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11897 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11899 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11903 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11906 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11908 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11909 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11911 return INTERP_KERNEL::NORM_ERROR;
11914 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11917 if(_conn_lgth!=NOTICABLE_FIRST_VAL)