1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
52 using namespace ParaMEDMEM;
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
56 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
58 MEDCouplingUMesh *MEDCouplingUMesh::New()
60 return new MEDCouplingUMesh;
63 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
65 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
66 ret->setName(meshName);
67 ret->setMeshDimension(meshDim);
72 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
73 * between \a this and the new mesh.
74 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
75 * delete this mesh using decrRef() as it is no more needed.
77 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
83 * Returns a new MEDCouplingMesh which is a copy of \a this one.
84 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
85 * this mesh are shared by the new mesh.
86 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
87 * delete this mesh using decrRef() as it is no more needed.
89 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
91 return new MEDCouplingUMesh(*this,recDeepCpy);
95 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
96 * The coordinates are shared between \a this and the returned instance.
98 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
99 * \sa MEDCouplingUMesh::deepCpy
101 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
103 checkConnectivityFullyDefined();
104 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
106 ret->setConnectivity(c,ci);
110 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
114 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
116 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
117 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
118 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
121 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
123 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
129 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
130 ret.push_back(_nodal_connec);
131 ret.push_back(_nodal_connec_index);
135 void MEDCouplingUMesh::updateTime() const
137 MEDCouplingPointSet::updateTime();
140 updateTimeWith(*_nodal_connec);
142 if(_nodal_connec_index)
144 updateTimeWith(*_nodal_connec_index);
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
153 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154 * then \a this mesh is most probably is writable, exchangeable and available for most
155 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156 * this method to check that all is in order with \a this mesh.
157 * \throw If the mesh dimension is not set.
158 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
159 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160 * \throw If the connectivity data array has more than one component.
161 * \throw If the connectivity data array has a named component.
162 * \throw If the connectivity index data array has more than one component.
163 * \throw If the connectivity index data array has a named component.
165 void MEDCouplingUMesh::checkCoherency() const
168 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
170 MEDCouplingPointSet::checkCoherency();
171 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
173 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
175 std::ostringstream message;
176 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177 throw INTERP_KERNEL::Exception(message.str().c_str());
182 if(_nodal_connec->getNumberOfComponents()!=1)
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184 if(_nodal_connec->getInfoOnComponent(0)!="")
185 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190 if(_nodal_connec_index)
192 if(_nodal_connec_index->getNumberOfComponents()!=1)
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194 if(_nodal_connec_index->getInfoOnComponent(0)!="")
195 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204 * then \a this mesh is most probably is writable, exchangeable and available for all
205 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206 * method thoroughly checks the nodal connectivity.
207 * \param [in] eps - a not used parameter.
208 * \throw If the mesh dimension is not set.
209 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
210 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211 * \throw If the connectivity data array has more than one component.
212 * \throw If the connectivity data array has a named component.
213 * \throw If the connectivity index data array has more than one component.
214 * \throw If the connectivity index data array has a named component.
215 * \throw If number of nodes defining an element does not correspond to the type of element.
216 * \throw If the nodal connectivity includes an invalid node id.
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
223 int meshDim=getMeshDimension();
224 int nbOfNodes=getNumberOfNodes();
225 int nbOfCells=getNumberOfCells();
226 const int *ptr=_nodal_connec->getConstPointer();
227 const int *ptrI=_nodal_connec_index->getConstPointer();
228 for(int i=0;i<nbOfCells;i++)
230 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231 if((int)cm.getDimension()!=meshDim)
233 std::ostringstream oss;
234 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235 throw INTERP_KERNEL::Exception(oss.str().c_str());
237 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
239 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
241 std::ostringstream oss;
242 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
243 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244 throw INTERP_KERNEL::Exception(oss.str().c_str());
246 if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
247 if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
249 std::ostringstream oss;
250 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " << nbOfNodesInCell;
251 oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
254 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
259 if(nodeId>=nbOfNodes)
261 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
262 throw INTERP_KERNEL::Exception(oss.str().c_str());
267 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
268 throw INTERP_KERNEL::Exception(oss.str().c_str());
272 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
274 std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
275 throw INTERP_KERNEL::Exception(oss.str().c_str());
284 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
285 * then \a this mesh is most probably is writable, exchangeable and available for all
286 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
287 * \param [in] eps - a not used parameter.
288 * \throw If the mesh dimension is not set.
289 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
290 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
291 * \throw If the connectivity data array has more than one component.
292 * \throw If the connectivity data array has a named component.
293 * \throw If the connectivity index data array has more than one component.
294 * \throw If the connectivity index data array has a named component.
295 * \throw If number of nodes defining an element does not correspond to the type of element.
296 * \throw If the nodal connectivity includes an invalid node id.
298 void MEDCouplingUMesh::checkCoherency2(double eps) const
300 checkCoherency1(eps);
304 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
305 * elements contained in the mesh. For more info on the mesh dimension see
306 * \ref MEDCouplingUMeshPage.
307 * \param [in] meshDim - a new mesh dimension.
308 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
310 void MEDCouplingUMesh::setMeshDimension(int meshDim)
312 if(meshDim<-1 || meshDim>3)
313 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
319 * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
320 * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
321 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
323 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
325 * \if ENABLE_EXAMPLES
326 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334 if(_nodal_connec_index)
336 _nodal_connec_index->decrRef();
340 _nodal_connec->decrRef();
342 _nodal_connec_index=DataArrayInt::New();
343 _nodal_connec_index->reserve(nbOfCells+1);
344 _nodal_connec_index->pushBackSilent(0);
345 _nodal_connec=DataArrayInt::New();
346 _nodal_connec->reserve(2*nbOfCells);
352 * Appends a cell to the connectivity array. For deeper understanding what is
353 * happening see \ref MEDCouplingUMeshNodalConnectivity.
354 * \param [in] type - type of cell to add.
355 * \param [in] size - number of nodes constituting this cell.
356 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
358 * \if ENABLE_EXAMPLES
359 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
365 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366 if(_nodal_connec_index==0)
367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368 if((int)cm.getDimension()==_mesh_dim)
371 if(size!=(int)cm.getNumberOfNodes())
373 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375 throw INTERP_KERNEL::Exception(oss.str().c_str());
377 int idx=_nodal_connec_index->back();
379 _nodal_connec_index->pushBackSilent(val);
380 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
385 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388 throw INTERP_KERNEL::Exception(oss.str().c_str());
393 * Compacts data arrays to release unused memory. This method is to be called after
394 * finishing cell insertion using \a this->insertNextCell().
396 * \if ENABLE_EXAMPLES
397 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
401 void MEDCouplingUMesh::finishInsertingCells()
403 _nodal_connec->pack();
404 _nodal_connec_index->pack();
405 _nodal_connec->declareAsNew();
406 _nodal_connec_index->declareAsNew();
411 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412 * Useful for python users.
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
416 return new MEDCouplingUMeshCellIterator(this);
420 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423 * Useful for python users.
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
427 if(!checkConsecutiveCellTypes())
428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429 return new MEDCouplingUMeshCellByTypeEntry(this);
433 * Returns a set of all cell types available in \a this mesh.
434 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435 * \warning this method does not throw any exception even if \a this is not defined.
436 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
444 * This method returns the sorted list of geometric types in \a this.
445 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
446 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
448 * \throw if connectivity in \a this is not correctly defined.
450 * \sa MEDCouplingMesh::getAllGeoTypes
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
454 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455 checkConnectivityFullyDefined();
456 int nbOfCells(getNumberOfCells());
459 if(getMeshLength()<1)
460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463 for(int i=1;i<nbOfCells;i++,ci++)
464 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
470 * This method is a method that compares \a this and \a other.
471 * This method compares \b all attributes, even names and component names.
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
476 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477 std::ostringstream oss; oss.precision(15);
478 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
481 reason="mesh given in input is not castable in MEDCouplingUMesh !";
484 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
486 if(_mesh_dim!=otherC->_mesh_dim)
488 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
492 if(_types!=otherC->_types)
494 oss << "umesh geometric type mismatch :\nThis geometric types are :";
495 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497 oss << "\nOther geometric types are :";
498 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
503 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504 if(_nodal_connec==0 || otherC->_nodal_connec==0)
506 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
509 if(_nodal_connec!=otherC->_nodal_connec)
510 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
512 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
515 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
518 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
521 if(_nodal_connec_index!=otherC->_nodal_connec_index)
522 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
524 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
531 * Checks if data arrays of this mesh (node coordinates, nodal
532 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
534 * \param [in] other - the mesh to compare with.
535 * \param [in] prec - precision value used to compare node coordinates.
536 * \return bool - \a true if the two meshes are same.
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
540 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
543 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
545 if(_mesh_dim!=otherC->_mesh_dim)
547 if(_types!=otherC->_types)
549 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550 if(_nodal_connec==0 || otherC->_nodal_connec==0)
552 if(_nodal_connec!=otherC->_nodal_connec)
553 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
555 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
558 if(_nodal_connec_index!=otherC->_nodal_connec_index)
559 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
565 * Checks if \a this and \a other meshes are geometrically equivalent with high
566 * probability, else an exception is thrown. The meshes are considered equivalent if
567 * (1) meshes contain the same number of nodes and the same number of elements of the
568 * same types (2) three cells of the two meshes (first, last and middle) are based
569 * on coincident nodes (with a specified precision).
570 * \param [in] other - the mesh to compare with.
571 * \param [in] prec - the precision used to compare nodes of the two meshes.
572 * \throw If the two meshes do not match.
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
576 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
583 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584 * cells each node belongs to.
585 * \warning For speed reasons, this method does not check if node ids in the nodal
586 * connectivity correspond to the size of node coordinates array.
587 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589 * dividing cell ids in \a revNodal into groups each referring to one
590 * node. Its every element (except the last one) is an index pointing to the
591 * first id of a group of cells. For example cells sharing the node #1 are
592 * described by following range of indices:
593 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595 * Number of cells sharing the *i*-th node is
596 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597 * \throw If the coordinates array is not set.
598 * \throw If the nodal connectivity of cells is not defined.
600 * \if ENABLE_EXAMPLES
601 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
608 int nbOfNodes=getNumberOfNodes();
609 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612 const int *conn=_nodal_connec->getConstPointer();
613 const int *connIndex=_nodal_connec_index->getConstPointer();
614 int nbOfCells=getNumberOfCells();
615 int nbOfEltsInRevNodal=0;
616 for(int eltId=0;eltId<nbOfCells;eltId++)
618 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621 if(*iter>=0)//for polyhedrons
623 nbOfEltsInRevNodal++;
624 revNodalIndxPtr[(*iter)+1]++;
627 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631 for(int eltId=0;eltId<nbOfCells;eltId++)
633 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636 if(*iter>=0)//for polyhedrons
637 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
654 if(cm.getOrientationStatus(nb,conn1,conn2))
661 class MinusOneSonsGenerator
664 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667 static const int DELTA=1;
669 const INTERP_KERNEL::CellModel& _cm;
672 class MinusOneSonsGeneratorBiQuadratic
675 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678 static const int DELTA=1;
680 const INTERP_KERNEL::CellModel& _cm;
683 class MinusTwoSonsGenerator
686 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689 static const int DELTA=2;
691 const INTERP_KERNEL::CellModel& _cm;
697 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699 * describing correspondence between cells of \a this and the result meshes are
700 * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
701 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702 * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
703 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
704 * \warning For speed reasons, this method does not check if node ids in the nodal
705 * connectivity correspond to the size of node coordinates array.
706 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707 * to write this mesh to the MED file, its cells must be sorted using
708 * sortCellsInMEDFileFrmt().
709 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
710 * each cell of \a this mesh.
711 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712 * dividing cell ids in \a desc into groups each referring to one
713 * cell of \a this mesh. Its every element (except the last one) is an index
714 * pointing to the first id of a group of cells. For example cells of the
715 * result mesh bounding the cell #1 of \a this mesh are described by following
717 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722 * by each cell of the result mesh.
723 * \param [in,out] revDescIndx - the array, of length one more than number of cells
724 * in the result mesh,
725 * dividing cell ids in \a revDesc into groups each referring to one
726 * cell of the result mesh the same way as \a descIndx divides \a desc.
727 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728 * delete this mesh using decrRef() as it is no more needed.
729 * \throw If the coordinates array is not set.
730 * \throw If the nodal connectivity of cells is node defined.
731 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732 * revDescIndx == NULL.
734 * \if ENABLE_EXAMPLES
735 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
738 * \sa buildDescendingConnectivity2()
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
742 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
746 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750 * \sa MEDCouplingUMesh::buildDescendingConnectivity
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
755 if(getMeshDimension()!=3)
756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
761 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762 * this->getMeshDimension(), that bound cells of \a this mesh. In
763 * addition arrays describing correspondence between cells of \a this and the result
764 * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
765 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766 * mesh. This method differs from buildDescendingConnectivity() in that apart
767 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768 * result meshes. So a positive id means that order of nodes in corresponding cells
769 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771 * i.e. cell ids are one-based.
772 * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
773 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
774 * \warning For speed reasons, this method does not check if node ids in the nodal
775 * connectivity correspond to the size of node coordinates array.
776 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777 * to write this mesh to the MED file, its cells must be sorted using
778 * sortCellsInMEDFileFrmt().
779 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
780 * each cell of \a this mesh.
781 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782 * dividing cell ids in \a desc into groups each referring to one
783 * cell of \a this mesh. Its every element (except the last one) is an index
784 * pointing to the first id of a group of cells. For example cells of the
785 * result mesh bounding the cell #1 of \a this mesh are described by following
787 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792 * by each cell of the result mesh.
793 * \param [in,out] revDescIndx - the array, of length one more than number of cells
794 * in the result mesh,
795 * dividing cell ids in \a revDesc into groups each referring to one
796 * cell of the result mesh the same way as \a descIndx divides \a desc.
797 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798 * shares the node coordinates array with \a this mesh. The caller is to
799 * delete this mesh using decrRef() as it is no more needed.
800 * \throw If the coordinates array is not set.
801 * \throw If the nodal connectivity of cells is node defined.
802 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803 * revDescIndx == NULL.
805 * \if ENABLE_EXAMPLES
806 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
809 * \sa buildDescendingConnectivity()
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
813 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
817 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818 * For speed reasons no check of this will be done. This method calls
819 * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
820 * This method lists cell by cell in \b this which are its neighbors. To compute the result
821 * only connectivities are considered.
822 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
823 * The format of return is hence \ref numbering-indirect.
825 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
826 * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
827 * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
828 * is equal to the last values in \b neighborsIndx.
829 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
830 * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
832 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
834 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
835 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
838 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
840 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
844 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
845 * of MEDCouplingUMesh::computeNeighborsOfCells.
846 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
847 * typically the case to extract a set a neighbours,
848 * excluding a set of meshdim-1 cells in input descending connectivity.
849 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
850 * the result of MEDCouplingUMesh::buildDescendingConnectivity.
851 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
853 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
855 * \param [in] desc descending connectivity array.
856 * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
857 * \param [in] revDesc reverse descending connectivity array.
858 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
859 * \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
860 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
861 * \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.
863 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
864 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
866 if(!desc || !descIndx || !revDesc || !revDescIndx)
867 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
868 const int *descPtr=desc->getConstPointer();
869 const int *descIPtr=descIndx->getConstPointer();
870 const int *revDescPtr=revDesc->getConstPointer();
871 const int *revDescIPtr=revDescIndx->getConstPointer();
873 int nbCells=descIndx->getNumberOfTuples()-1;
874 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
876 int *out1Ptr=out1->getPointer();
878 out0->reserve(desc->getNumberOfTuples());
879 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
881 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
883 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
885 out0->insertAtTheEnd(s.begin(),s.end());
887 *out1Ptr=out0->getNumberOfTuples();
889 neighbors=out0.retn();
890 neighborsIndx=out1.retn();
894 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
895 * For speed reasons no check of this will be done. This method calls
896 * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
897 * This method lists node by node in \b this which are its neighbors. To compute the result
898 * only connectivities are considered.
899 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
901 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
902 * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
903 * parameter allows to select the right part in this array (\ref numbering-indirect).
904 * The number of tuples is equal to the last values in \b neighborsIndx.
905 * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
906 * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
908 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
911 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
913 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
918 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
923 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
928 mesh1D=const_cast<MEDCouplingUMesh *>(this);
934 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
937 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
938 mesh1D->getReverseNodalConnectivity(desc,descIndx);
939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
940 ret0->alloc(desc->getNumberOfTuples(),1);
941 int *r0Pt(ret0->getPointer());
942 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
943 for(int i=0;i<nbNodes;i++,rni++)
945 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
946 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
948 neighbors=ret0.retn();
949 neighborsIdx=descIndx.retn();
955 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
956 * For speed reasons no check of this will be done.
958 template<class SonsGenerator>
959 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
961 if(!desc || !descIndx || !revDesc || !revDescIndx)
962 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
963 checkConnectivityFullyDefined();
964 int nbOfCells=getNumberOfCells();
965 int nbOfNodes=getNumberOfNodes();
966 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
967 int *revNodalIndxPtr=revNodalIndx->getPointer();
968 const int *conn=_nodal_connec->getConstPointer();
969 const int *connIndex=_nodal_connec_index->getConstPointer();
970 std::string name="Mesh constituent of "; name+=getName();
971 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
972 ret->setCoords(getCoords());
973 ret->allocateCells(2*nbOfCells);
974 descIndx->alloc(nbOfCells+1,1);
975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
976 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
977 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
979 int pos=connIndex[eltId];
980 int posP1=connIndex[eltId+1];
981 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
982 SonsGenerator sg(cm);
983 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
984 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
985 for(unsigned i=0;i<nbOfSons;i++)
987 INTERP_KERNEL::NormalizedCellType cmsId;
988 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
989 for(unsigned k=0;k<nbOfNodesSon;k++)
991 revNodalIndxPtr[tmp[k]+1]++;
992 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
993 revDesc2->pushBackSilent(eltId);
995 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
997 int nbOfCellsM1=ret->getNumberOfCells();
998 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1000 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1001 int *revNodalPtr=revNodal->getPointer();
1002 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1003 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1004 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1006 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1007 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1008 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1009 if(*iter>=0)//for polyhedrons
1010 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1013 DataArrayInt *commonCells=0,*commonCellsI=0;
1014 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1016 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1017 int newNbOfCellsM1=-1;
1018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1019 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1020 std::vector<bool> isImpacted(nbOfCellsM1,false);
1021 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1022 for(int work2=work[0];work2!=work[1];work2++)
1023 isImpacted[commonCellsPtr[work2]]=true;
1024 const int *o2nM1Ptr=o2nM1->getConstPointer();
1025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1026 const int *n2oM1Ptr=n2oM1->getConstPointer();
1027 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1028 ret2->copyTinyInfoFrom(this);
1029 desc->alloc(descIndx->back(),1);
1030 int *descPtr=desc->getPointer();
1031 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1032 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1035 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1038 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1040 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1041 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1044 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1047 revDesc->reserve(newNbOfCellsM1);
1048 revDescIndx->alloc(newNbOfCellsM1+1,1);
1049 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1050 const int *revDesc2Ptr=revDesc2->getConstPointer();
1051 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1053 int oldCellIdM1=n2oM1Ptr[i];
1054 if(!isImpacted[oldCellIdM1])
1056 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1057 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1061 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1062 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1063 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1071 struct MEDCouplingAccVisit
1073 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1074 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1075 int _new_nb_of_nodes;
1081 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1082 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1083 * array of cell ids. Pay attention that after conversion all algorithms work slower
1084 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1085 * conversion due presence of invalid ids in the array of cells to convert, as a
1086 * result \a this mesh contains some already converted elements. In this case the 2D
1087 * mesh remains valid but 3D mesh becomes \b inconsistent!
1088 * \warning This method can significantly modify the order of geometric types in \a this,
1089 * hence, to write this mesh to the MED file, its cells must be sorted using
1090 * sortCellsInMEDFileFrmt().
1091 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1092 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1093 * cellIdsToConvertBg.
1094 * \throw If the coordinates array is not set.
1095 * \throw If the nodal connectivity of cells is node defined.
1096 * \throw If dimension of \a this mesh is not either 2 or 3.
1098 * \if ENABLE_EXAMPLES
1099 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1100 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1103 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1105 checkFullyDefined();
1106 int dim=getMeshDimension();
1108 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1109 int nbOfCells(getNumberOfCells());
1112 const int *connIndex=_nodal_connec_index->getConstPointer();
1113 int *conn=_nodal_connec->getPointer();
1114 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1116 if(*iter>=0 && *iter<nbOfCells)
1118 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1119 if(!cm.isQuadratic())
1120 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1122 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1126 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1127 oss << " in range [0," << nbOfCells << ") !";
1128 throw INTERP_KERNEL::Exception(oss.str().c_str());
1134 int *connIndex(_nodal_connec_index->getPointer());
1135 const int *connOld(_nodal_connec->getConstPointer());
1136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1137 std::vector<bool> toBeDone(nbOfCells,false);
1138 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1140 if(*iter>=0 && *iter<nbOfCells)
1141 toBeDone[*iter]=true;
1144 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1145 oss << " in range [0," << nbOfCells << ") !";
1146 throw INTERP_KERNEL::Exception(oss.str().c_str());
1149 for(int cellId=0;cellId<nbOfCells;cellId++)
1151 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1152 int lgthOld(posP1-pos-1);
1153 if(toBeDone[cellId])
1155 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1156 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1157 int *tmp(new int[nbOfFaces*lgthOld+1]);
1158 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1159 for(unsigned j=0;j<nbOfFaces;j++)
1161 INTERP_KERNEL::NormalizedCellType type;
1162 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1166 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1167 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1168 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1173 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1174 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1177 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1183 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1184 * polyhedrons (if \a this is a 3D mesh).
1185 * \warning As this method is purely for user-friendliness and no optimization is
1186 * done to avoid construction of a useless vector, this method can be costly
1188 * \throw If the coordinates array is not set.
1189 * \throw If the nodal connectivity of cells is node defined.
1190 * \throw If dimension of \a this mesh is not either 2 or 3.
1192 void MEDCouplingUMesh::convertAllToPoly()
1194 int nbOfCells=getNumberOfCells();
1195 std::vector<int> cellIds(nbOfCells);
1196 for(int i=0;i<nbOfCells;i++)
1198 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1202 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1203 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1204 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1205 * base facet of the volume and the second half of nodes describes an opposite facet
1206 * having the same number of nodes as the base one. This method converts such
1207 * connectivity to a valid polyhedral format where connectivity of each facet is
1208 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1209 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1210 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1211 * a correct orientation of the first facet of a polyhedron, else orientation of a
1212 * corrected cell is reverse.<br>
1213 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1214 * it releases the user from boring description of polyhedra connectivity in the valid
1216 * \throw If \a this->getMeshDimension() != 3.
1217 * \throw If \a this->getSpaceDimension() != 3.
1218 * \throw If the nodal connectivity of cells is not defined.
1219 * \throw If the coordinates array is not set.
1220 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1221 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1223 * \if ENABLE_EXAMPLES
1224 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1225 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1228 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1230 checkFullyDefined();
1231 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1232 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1233 int nbOfCells=getNumberOfCells();
1234 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1235 newCi->alloc(nbOfCells+1,1);
1236 int *newci=newCi->getPointer();
1237 const int *ci=_nodal_connec_index->getConstPointer();
1238 const int *c=_nodal_connec->getConstPointer();
1240 for(int i=0;i<nbOfCells;i++)
1242 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243 if(type==INTERP_KERNEL::NORM_POLYHED)
1245 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1247 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1248 throw INTERP_KERNEL::Exception(oss.str().c_str());
1250 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1253 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 !";
1254 throw INTERP_KERNEL::Exception(oss.str().c_str());
1257 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)
1260 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1263 newC->alloc(newci[nbOfCells],1);
1264 int *newc=newC->getPointer();
1265 for(int i=0;i<nbOfCells;i++)
1267 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1268 if(type==INTERP_KERNEL::NORM_POLYHED)
1270 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1271 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1273 for(std::size_t j=0;j<n1;j++)
1275 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1277 newc[n1+5*j+1]=c[ci[i]+1+j];
1278 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1279 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1280 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1285 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1287 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1288 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1293 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1294 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1295 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1296 * to write this mesh to the MED file, its cells must be sorted using
1297 * sortCellsInMEDFileFrmt().
1298 * \return \c true if at least one cell has been converted, \c false else. In the
1299 * last case the nodal connectivity remains unchanged.
1300 * \throw If the coordinates array is not set.
1301 * \throw If the nodal connectivity of cells is not defined.
1302 * \throw If \a this->getMeshDimension() < 0.
1304 bool MEDCouplingUMesh::unPolyze()
1306 checkFullyDefined();
1307 int mdim=getMeshDimension();
1309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1312 int nbOfCells=getNumberOfCells();
1315 int initMeshLgth=getMeshLength();
1316 int *conn=_nodal_connec->getPointer();
1317 int *index=_nodal_connec_index->getPointer();
1322 for(int i=0;i<nbOfCells;i++)
1324 lgthOfCurCell=index[i+1]-posOfCurCell;
1325 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1326 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1327 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1331 switch(cm.getDimension())
1335 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1336 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1337 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1342 int nbOfFaces,lgthOfPolyhConn;
1343 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1344 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1349 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1353 ret=ret || (newType!=type);
1354 conn[newPos]=newType;
1356 posOfCurCell=index[i+1];
1361 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1362 newPos+=lgthOfCurCell;
1363 posOfCurCell+=lgthOfCurCell;
1367 if(newPos!=initMeshLgth)
1368 _nodal_connec->reAlloc(newPos);
1375 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1376 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1377 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1379 * \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
1382 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1384 checkFullyDefined();
1385 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1386 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1387 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1388 coords->recenterForMaxPrecision(eps);
1390 int nbOfCells=getNumberOfCells();
1391 const int *conn=_nodal_connec->getConstPointer();
1392 const int *index=_nodal_connec_index->getConstPointer();
1393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1394 connINew->alloc(nbOfCells+1,1);
1395 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1398 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1400 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1402 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1406 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1407 *connINewPtr=connNew->getNumberOfTuples();
1410 setConnectivity(connNew,connINew,false);
1414 * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1415 * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1416 * the format of the returned DataArrayInt instance.
1418 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1419 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1421 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1423 checkConnectivityFullyDefined();
1424 int nbOfCells=getNumberOfCells();
1425 const int *connIndex=_nodal_connec_index->getConstPointer();
1426 const int *conn=_nodal_connec->getConstPointer();
1427 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1428 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1429 std::vector<bool> retS(maxElt,false);
1430 for(int i=0;i<nbOfCells;i++)
1431 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1435 for(int i=0;i<maxElt;i++)
1438 DataArrayInt *ret=DataArrayInt::New();
1440 int *retPtr=ret->getPointer();
1441 for(int i=0;i<maxElt;i++)
1448 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1449 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1451 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1453 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1454 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1455 for(int i=0;i<nbOfCells;i++)
1456 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1459 if(conn[j]<nbOfNodes)
1460 nodeIdsInUse[conn[j]]=true;
1463 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1464 throw INTERP_KERNEL::Exception(oss.str().c_str());
1470 * Finds nodes not used in any cell and returns an array giving a new id to every node
1471 * by excluding the unused nodes, for which the array holds -1. The result array is
1472 * a mapping in "Old to New" mode.
1473 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1474 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1475 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1476 * if the node is unused or a new id else. The caller is to delete this
1477 * array using decrRef() as it is no more needed.
1478 * \throw If the coordinates array is not set.
1479 * \throw If the nodal connectivity of cells is not defined.
1480 * \throw If the nodal connectivity includes an invalid id.
1482 * \if ENABLE_EXAMPLES
1483 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1484 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1486 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1488 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1491 int nbOfNodes(getNumberOfNodes());
1492 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1493 ret->alloc(nbOfNodes,1);
1494 int *traducer=ret->getPointer();
1495 std::fill(traducer,traducer+nbOfNodes,-1);
1496 int nbOfCells=getNumberOfCells();
1497 const int *connIndex=_nodal_connec_index->getConstPointer();
1498 const int *conn=_nodal_connec->getConstPointer();
1499 for(int i=0;i<nbOfCells;i++)
1500 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1503 if(conn[j]<nbOfNodes)
1504 traducer[conn[j]]=1;
1507 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1508 throw INTERP_KERNEL::Exception(oss.str().c_str());
1511 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1512 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1517 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1518 * For each cell in \b this the number of nodes constituting cell is computed.
1519 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1520 * So for pohyhedrons some nodes can be counted several times in the returned result.
1522 * \return a newly allocated array
1523 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1525 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1527 checkConnectivityFullyDefined();
1528 int nbOfCells=getNumberOfCells();
1529 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1530 ret->alloc(nbOfCells,1);
1531 int *retPtr=ret->getPointer();
1532 const int *conn=getNodalConnectivity()->getConstPointer();
1533 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1534 for(int i=0;i<nbOfCells;i++,retPtr++)
1536 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1537 *retPtr=connI[i+1]-connI[i]-1;
1539 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1545 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1546 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1548 * \return DataArrayInt * - new object to be deallocated by the caller.
1549 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1551 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1553 checkConnectivityFullyDefined();
1554 int nbOfCells=getNumberOfCells();
1555 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1556 ret->alloc(nbOfCells,1);
1557 int *retPtr=ret->getPointer();
1558 const int *conn=getNodalConnectivity()->getConstPointer();
1559 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1560 for(int i=0;i<nbOfCells;i++,retPtr++)
1562 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1563 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1564 *retPtr=(int)s.size();
1568 *retPtr=(int)s.size();
1575 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1576 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1578 * \return a newly allocated array
1580 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1582 checkConnectivityFullyDefined();
1583 int nbOfCells=getNumberOfCells();
1584 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1585 ret->alloc(nbOfCells,1);
1586 int *retPtr=ret->getPointer();
1587 const int *conn=getNodalConnectivity()->getConstPointer();
1588 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1589 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1591 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1592 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1598 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1599 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1600 * array mean that the corresponding old node is no more used.
1601 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1602 * this->getNumberOfNodes() before call of this method. The caller is to
1603 * delete this array using decrRef() as it is no more needed.
1604 * \throw If the coordinates array is not set.
1605 * \throw If the nodal connectivity of cells is not defined.
1606 * \throw If the nodal connectivity includes an invalid id.
1607 * \sa areAllNodesFetched
1609 * \if ENABLE_EXAMPLES
1610 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1611 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1614 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1616 return MEDCouplingPointSet::zipCoordsTraducer();
1620 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1621 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1623 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1628 return AreCellsEqual0(conn,connI,cell1,cell2);
1630 return AreCellsEqual1(conn,connI,cell1,cell2);
1632 return AreCellsEqual2(conn,connI,cell1,cell2);
1634 return AreCellsEqual3(conn,connI,cell1,cell2);
1636 return AreCellsEqual7(conn,connI,cell1,cell2);
1638 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1642 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1644 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1646 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1647 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1652 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1654 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1656 int sz=connI[cell1+1]-connI[cell1];
1657 if(sz==connI[cell2+1]-connI[cell2])
1659 if(conn[connI[cell1]]==conn[connI[cell2]])
1661 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1662 unsigned dim=cm.getDimension();
1668 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1669 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1670 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1671 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1672 return work!=tmp+sz1?1:0;
1675 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1685 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1687 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1689 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1691 if(conn[connI[cell1]]==conn[connI[cell2]])
1693 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1702 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1704 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1706 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1708 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1709 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1716 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1718 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1720 int sz=connI[cell1+1]-connI[cell1];
1721 if(sz==connI[cell2+1]-connI[cell2])
1723 if(conn[connI[cell1]]==conn[connI[cell2]])
1725 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1726 unsigned dim=cm.getDimension();
1732 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1733 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1734 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1735 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1740 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1741 std::reverse_iterator<int *> it2((int *)tmp);
1742 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1748 return work!=tmp+sz1?1:0;
1751 {//case of SEG2 and SEG3
1752 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1754 if(!cm.isQuadratic())
1756 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1757 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1758 if(std::equal(it1,it2,conn+connI[cell2]+1))
1764 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])
1771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1778 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1779 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1780 * and result remains unchanged.
1781 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1782 * If in 'candidates' pool -1 value is considered as an empty value.
1783 * WARNING this method returns only ONE set of result !
1785 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1787 if(candidates.size()<1)
1790 std::vector<int>::const_iterator iter=candidates.begin();
1791 int start=(*iter++);
1792 for(;iter!=candidates.end();iter++)
1794 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1799 result->pushBackSilent(start);
1803 result->pushBackSilent(*iter);
1805 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1812 * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1814 * This method keeps the coordiantes of \a this. This method is time consuming.
1816 * \param [in] compType input specifying the technique used to compare cells each other.
1817 * - 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.
1818 * - 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)
1819 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1820 * - 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
1821 * can be used for users not sensitive to orientation of cell
1822 * \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.
1823 * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1824 * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1825 * \return the correspondance array old to new in a newly allocated array.
1828 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1831 getReverseNodalConnectivity(revNodal,revNodalI);
1832 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1835 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1836 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1839 int nbOfCells=nodalI->getNumberOfTuples()-1;
1840 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1841 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1842 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1843 std::vector<bool> isFetched(nbOfCells,false);
1846 for(int i=0;i<nbOfCells;i++)
1850 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1851 std::vector<int> v,v2;
1852 if(connOfNode!=connPtr+connIPtr[i+1])
1854 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1855 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1858 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1862 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1863 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1864 v2.resize(std::distance(v2.begin(),it));
1868 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1870 int pos=commonCellsI->back();
1871 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1872 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1873 isFetched[*it]=true;
1881 for(int i=startCellId;i<nbOfCells;i++)
1885 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1886 std::vector<int> v,v2;
1887 if(connOfNode!=connPtr+connIPtr[i+1])
1889 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1892 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1896 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1897 v2.resize(std::distance(v2.begin(),it));
1901 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1903 int pos=commonCellsI->back();
1904 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1905 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1906 isFetched[*it]=true;
1912 commonCellsArr=commonCells.retn();
1913 commonCellsIArr=commonCellsI.retn();
1917 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1918 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1919 * than \a other->getNumberOfCells() in the returned array means that there is no
1920 * corresponding cell in \a this mesh.
1921 * It is expected that \a this and \a other meshes share the same node coordinates
1922 * array, if it is not so an exception is thrown.
1923 * \param [in] other - the mesh to compare with.
1924 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1925 * valid values [0,1,2], see zipConnectivityTraducer().
1926 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1927 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1928 * values. The caller is to delete this array using
1929 * decrRef() as it is no more needed.
1930 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1933 * \if ENABLE_EXAMPLES
1934 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1935 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1937 * \sa checkDeepEquivalOnSameNodesWith()
1938 * \sa checkGeoEquivalWith()
1940 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1942 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1943 int nbOfCells=getNumberOfCells();
1944 static const int possibleCompType[]={0,1,2};
1945 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1947 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1948 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1950 throw INTERP_KERNEL::Exception(oss.str().c_str());
1952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1953 arr=o2n->substr(nbOfCells);
1954 arr->setName(other->getName());
1956 if(other->getNumberOfCells()==0)
1958 return arr->getMaxValue(tmp)<nbOfCells;
1962 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1963 * This method tries to determine if \b other is fully included in \b this.
1964 * The main difference is that this method is not expected to throw exception.
1965 * This method has two outputs :
1967 * \param other other mesh
1968 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1969 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1971 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1973 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1974 DataArrayInt *commonCells=0,*commonCellsI=0;
1975 int thisNbCells=getNumberOfCells();
1976 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1978 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1979 int otherNbCells=other->getNumberOfCells();
1980 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1981 arr2->alloc(otherNbCells,1);
1982 arr2->fillWithZero();
1983 int *arr2Ptr=arr2->getPointer();
1984 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1985 for(int i=0;i<nbOfCommon;i++)
1987 int start=commonCellsPtr[commonCellsIPtr[i]];
1988 if(start<thisNbCells)
1990 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1992 int sig=commonCellsPtr[j]>0?1:-1;
1993 int val=std::abs(commonCellsPtr[j])-1;
1994 if(val>=thisNbCells)
1995 arr2Ptr[val-thisNbCells]=sig*(start+1);
1999 arr2->setName(other->getName());
2000 if(arr2->presenceOfValue(0))
2006 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2009 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2010 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2013 std::vector<const MEDCouplingUMesh *> ms(2);
2016 return MergeUMeshesOnSameCoords(ms);
2020 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2021 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2022 * cellIds is not given explicitely but by a range python like.
2027 * \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.
2028 * \return a newly allocated
2030 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2031 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2033 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2035 if(getMeshDimension()!=-1)
2036 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2039 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2041 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2043 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2045 return const_cast<MEDCouplingUMesh *>(this);
2050 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2051 * The result mesh shares or not the node coordinates array with \a this mesh depending
2052 * on \a keepCoords parameter.
2053 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2054 * to write this mesh to the MED file, its cells must be sorted using
2055 * sortCellsInMEDFileFrmt().
2056 * \param [in] begin - an array of cell ids to include to the new mesh.
2057 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2058 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2059 * array of \a this mesh, else "free" nodes are removed from the result mesh
2060 * by calling zipCoords().
2061 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2062 * to delete this mesh using decrRef() as it is no more needed.
2063 * \throw If the coordinates array is not set.
2064 * \throw If the nodal connectivity of cells is not defined.
2065 * \throw If any cell id in the array \a begin is not valid.
2067 * \if ENABLE_EXAMPLES
2068 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2069 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2072 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2074 if(getMeshDimension()!=-1)
2075 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2079 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2081 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2083 return const_cast<MEDCouplingUMesh *>(this);
2088 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2090 * 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.
2091 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2092 * The number of cells of \b this will remain the same with this method.
2094 * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2095 * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2096 * \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 ).
2097 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2099 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2101 checkConnectivityFullyDefined();
2102 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2103 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2104 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2105 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2107 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2108 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2109 throw INTERP_KERNEL::Exception(oss.str().c_str());
2111 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2112 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2114 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2115 throw INTERP_KERNEL::Exception(oss.str().c_str());
2117 int nbOfCells=getNumberOfCells();
2118 bool easyAssign=true;
2119 const int *connI=_nodal_connec_index->getConstPointer();
2120 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2121 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2123 if(*it>=0 && *it<nbOfCells)
2125 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2129 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2130 throw INTERP_KERNEL::Exception(oss.str().c_str());
2135 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2140 DataArrayInt *arrOut=0,*arrIOut=0;
2141 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2144 setConnectivity(arrOut,arrIOut,true);
2148 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2150 checkConnectivityFullyDefined();
2151 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2152 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2153 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2154 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2156 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2157 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2158 throw INTERP_KERNEL::Exception(oss.str().c_str());
2160 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2161 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2163 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2164 throw INTERP_KERNEL::Exception(oss.str().c_str());
2166 int nbOfCells=getNumberOfCells();
2167 bool easyAssign=true;
2168 const int *connI=_nodal_connec_index->getConstPointer();
2169 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2171 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2173 if(it>=0 && it<nbOfCells)
2175 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2179 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2180 throw INTERP_KERNEL::Exception(oss.str().c_str());
2185 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2190 DataArrayInt *arrOut=0,*arrIOut=0;
2191 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2193 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2194 setConnectivity(arrOut,arrIOut,true);
2199 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2200 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2201 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2202 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2204 * \param [in] begin input start of array of node ids.
2205 * \param [in] end input end of array of node ids.
2206 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2207 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2209 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2212 checkConnectivityFullyDefined();
2214 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2215 std::vector<bool> fastFinder(sz,false);
2216 for(const int *work=begin;work!=end;work++)
2217 if(*work>=0 && *work<sz)
2218 fastFinder[*work]=true;
2219 int nbOfCells=getNumberOfCells();
2220 const int *conn=getNodalConnectivity()->getConstPointer();
2221 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2222 for(int i=0;i<nbOfCells;i++)
2224 int ref=0,nbOfHit=0;
2225 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2229 if(fastFinder[*work2])
2232 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2233 cellIdsKept->pushBackSilent(i);
2235 cellIdsKeptArr=cellIdsKept.retn();
2239 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2240 * this->getMeshDimension(), that bound some cells of \a this mesh.
2241 * The cells of lower dimension to include to the result mesh are selected basing on
2242 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2243 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2244 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2245 * created mesh shares the node coordinates array with \a this mesh.
2246 * \param [in] begin - the array of node ids.
2247 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2248 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2249 * array \a begin are added, else cells whose any node is in the
2250 * array \a begin are added.
2251 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2252 * to delete this mesh using decrRef() as it is no more needed.
2253 * \throw If the coordinates array is not set.
2254 * \throw If the nodal connectivity of cells is not defined.
2255 * \throw If any node id in \a begin is not valid.
2257 * \if ENABLE_EXAMPLES
2258 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2259 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2262 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2264 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2265 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2266 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2267 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2268 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2272 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2273 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2274 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2275 * array of \a this mesh, else "free" nodes are removed from the result mesh
2276 * by calling zipCoords().
2277 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2278 * to delete this mesh using decrRef() as it is no more needed.
2279 * \throw If the coordinates array is not set.
2280 * \throw If the nodal connectivity of cells is not defined.
2282 * \if ENABLE_EXAMPLES
2283 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2284 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2287 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2289 DataArrayInt *desc=DataArrayInt::New();
2290 DataArrayInt *descIndx=DataArrayInt::New();
2291 DataArrayInt *revDesc=DataArrayInt::New();
2292 DataArrayInt *revDescIndx=DataArrayInt::New();
2294 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2297 descIndx->decrRef();
2298 int nbOfCells=meshDM1->getNumberOfCells();
2299 const int *revDescIndxC=revDescIndx->getConstPointer();
2300 std::vector<int> boundaryCells;
2301 for(int i=0;i<nbOfCells;i++)
2302 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2303 boundaryCells.push_back(i);
2304 revDescIndx->decrRef();
2305 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2310 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2311 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2312 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2314 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2316 checkFullyDefined();
2317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2322 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2323 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2326 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2327 const int *revDescPtr=revDesc->getConstPointer();
2328 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2329 int nbOfCells=getNumberOfCells();
2330 std::vector<bool> ret1(nbOfCells,false);
2332 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2333 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2334 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2336 DataArrayInt *ret2=DataArrayInt::New();
2338 int *ret2Ptr=ret2->getPointer();
2340 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2343 ret2->setName("BoundaryCells");
2348 * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2349 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2350 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2351 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2353 * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2354 * 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
2355 * equals a cell in \b otherDimM1OnSameCoords.
2357 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2358 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2360 * \param [in] otherDimM1OnSameCoords
2361 * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2362 * \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
2363 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2365 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2367 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2369 checkConnectivityFullyDefined();
2370 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2371 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2372 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2375 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2377 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2378 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2379 DataArrayInt *idsOtherInConsti=0;
2380 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2383 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2385 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2386 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2388 s1arr_renum1->sort();
2389 cellIdsRk0=s0arr.retn();
2390 //cellIdsRk1=s_renum1.retn();
2391 cellIdsRk1=s1arr_renum1.retn();
2395 * 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
2396 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2398 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2400 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2407 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2408 revDesc=0; desc=0; descIndx=0;
2409 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2410 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2411 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2415 * Finds nodes lying on the boundary of \a this mesh.
2416 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2417 * nodes. The caller is to delete this array using decrRef() as it is no
2419 * \throw If the coordinates array is not set.
2420 * \throw If the nodal connectivity of cells is node defined.
2422 * \if ENABLE_EXAMPLES
2423 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2424 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2427 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2429 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2430 return skin->computeFetchedNodeIds();
2433 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2436 return const_cast<MEDCouplingUMesh *>(this);
2440 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2441 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2442 * 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.
2443 * 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.
2444 * 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.
2446 * \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
2447 * parameter is altered during the call.
2448 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2449 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2450 * \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.
2452 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2454 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2455 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2457 typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2459 checkFullyDefined();
2460 otherDimM1OnSameCoords.checkFullyDefined();
2461 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2463 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2465 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2466 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2467 DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2468 DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2469 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2470 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2471 DAInt s1=m0Part->computeFetchedNodeIds();
2472 DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2473 DAInt s3=s2->buildSubstraction(s1);
2474 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2476 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2477 int nCells2 = m0Part2->getNumberOfCells();
2478 DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2479 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2480 // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2481 DataArrayInt *tmp00=0,*tmp11=0;
2482 MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2483 DAInt neighInit00(tmp00);
2484 DAInt neighIInit00(tmp11);
2485 // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2486 DataArrayInt *idsTmp=0;
2487 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2490 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2491 // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2492 // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2493 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2494 DataArrayInt *tmp0=0,*tmp1=0;
2495 // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2496 // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2497 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2498 DAInt neigh00(tmp0);
2499 DAInt neighI00(tmp1);
2501 // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2502 int seed = 0, nIter = 0;
2503 int nIterMax = nCells2+1; // Safety net for the loop
2504 DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2505 hitCells->fillWithValue(-1);
2506 DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2507 cellsToModifyConn0_torenum->alloc(0,1);
2508 while (nIter < nIterMax)
2510 DAInt t = hitCells->getIdsEqual(-1);
2511 if (!t->getNumberOfTuples())
2513 // Connex zone without the crack (to compute the next seed really)
2515 DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2517 for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2518 hitCells->setIJ(*ptr,0,1);
2519 // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2520 DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2521 cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2522 // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2523 DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2524 DAInt nonHitCells = hitCells->getIdsEqual(-1);
2525 DAInt intersec = nonHitCells->buildIntersection(comple);
2526 if (intersec->getNumberOfTuples())
2527 { seed = intersec->getIJ(0,0); }
2532 if (nIter >= nIterMax)
2533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2535 DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2536 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2537 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2539 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2540 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2541 nodeIdsToDuplicate=s3.retn();
2545 * This method operates a modification of the connectivity and coords in \b this.
2546 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2547 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2548 * 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
2549 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2550 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2552 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2554 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2555 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2557 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2559 int nbOfNodes=getNumberOfNodes();
2560 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2561 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2565 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2566 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2568 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2570 * \sa renumberNodesInConn
2572 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2574 checkConnectivityFullyDefined();
2575 int *conn(getNodalConnectivity()->getPointer());
2576 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2577 int nbOfCells(getNumberOfCells());
2578 for(int i=0;i<nbOfCells;i++)
2579 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2581 int& node=conn[iconn];
2582 if(node>=0)//avoid polyhedron separator
2587 _nodal_connec->declareAsNew();
2592 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2593 * 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
2596 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2598 checkConnectivityFullyDefined();
2599 int *conn(getNodalConnectivity()->getPointer());
2600 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2601 int nbOfCells(getNumberOfCells());
2602 for(int i=0;i<nbOfCells;i++)
2603 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2605 int& node=conn[iconn];
2606 if(node>=0)//avoid polyhedron separator
2608 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2609 if(it!=newNodeNumbersO2N.end())
2615 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2616 throw INTERP_KERNEL::Exception(oss.str().c_str());
2620 _nodal_connec->declareAsNew();
2625 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2626 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2627 * This method is a generalization of shiftNodeNumbersInConn().
2628 * \warning This method performs no check of validity of new ids. **Use it with care !**
2629 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2630 * this->getNumberOfNodes(), in "Old to New" mode.
2631 * See \ref numbering for more info on renumbering modes.
2632 * \throw If the nodal connectivity of cells is not defined.
2634 * \if ENABLE_EXAMPLES
2635 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2636 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2639 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2641 checkConnectivityFullyDefined();
2642 int *conn=getNodalConnectivity()->getPointer();
2643 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2644 int nbOfCells(getNumberOfCells());
2645 for(int i=0;i<nbOfCells;i++)
2646 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2648 int& node=conn[iconn];
2649 if(node>=0)//avoid polyhedron separator
2651 node=newNodeNumbersO2N[node];
2654 _nodal_connec->declareAsNew();
2659 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2660 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2661 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2663 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2665 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2667 checkConnectivityFullyDefined();
2668 int *conn=getNodalConnectivity()->getPointer();
2669 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2670 int nbOfCells=getNumberOfCells();
2671 for(int i=0;i<nbOfCells;i++)
2672 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2674 int& node=conn[iconn];
2675 if(node>=0)//avoid polyhedron separator
2680 _nodal_connec->declareAsNew();
2685 * This method operates a modification of the connectivity in \b this.
2686 * 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.
2687 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2688 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2689 * 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
2690 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2691 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2693 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2694 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2696 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2697 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2698 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2700 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2702 checkConnectivityFullyDefined();
2703 std::map<int,int> m;
2705 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2707 int *conn=getNodalConnectivity()->getPointer();
2708 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2709 int nbOfCells=getNumberOfCells();
2710 for(int i=0;i<nbOfCells;i++)
2711 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2713 int& node=conn[iconn];
2714 if(node>=0)//avoid polyhedron separator
2716 std::map<int,int>::iterator it=m.find(node);
2725 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2727 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2728 * After the call of this method the number of cells remains the same as before.
2730 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2731 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2732 * be strictly in [0;this->getNumberOfCells()).
2734 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2735 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2736 * should be contained in[0;this->getNumberOfCells()).
2738 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2741 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2743 checkConnectivityFullyDefined();
2744 int nbCells=getNumberOfCells();
2745 const int *array=old2NewBg;
2747 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2749 const int *conn=_nodal_connec->getConstPointer();
2750 const int *connI=_nodal_connec_index->getConstPointer();
2751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2753 const int *n2oPtr=n2o->begin();
2754 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2755 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2756 newConn->copyStringInfoFrom(*_nodal_connec);
2757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2758 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2759 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2761 int *newC=newConn->getPointer();
2762 int *newCI=newConnI->getPointer();
2765 for(int i=0;i<nbCells;i++)
2768 int nbOfElts=connI[pos+1]-connI[pos];
2769 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2774 setConnectivity(newConn,newConnI);
2776 free(const_cast<int *>(array));
2780 * Finds cells whose bounding boxes intersect a given bounding box.
2781 * \param [in] bbox - an array defining the bounding box via coordinates of its
2782 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2784 * \param [in] eps - a factor used to increase size of the bounding box of cell
2785 * before comparing it with \a bbox. This factor is multiplied by the maximal
2786 * extent of the bounding box of cell to produce an addition to this bounding box.
2787 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2788 * cells. The caller is to delete this array using decrRef() as it is no more
2790 * \throw If the coordinates array is not set.
2791 * \throw If the nodal connectivity of cells is not defined.
2793 * \if ENABLE_EXAMPLES
2794 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2795 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2798 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2801 if(getMeshDimension()==-1)
2803 elems->pushBackSilent(0);
2804 return elems.retn();
2806 int dim=getSpaceDimension();
2807 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2808 const int* conn = getNodalConnectivity()->getConstPointer();
2809 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2810 const double* coords = getCoords()->getConstPointer();
2811 int nbOfCells=getNumberOfCells();
2812 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2814 for (int i=0; i<dim; i++)
2816 elem_bb[i*2]=std::numeric_limits<double>::max();
2817 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2820 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2822 int node= conn[inode];
2823 if(node>=0)//avoid polyhedron separator
2825 for (int idim=0; idim<dim; idim++)
2827 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2829 elem_bb[idim*2] = coords[node*dim+idim] ;
2831 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2833 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2838 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2839 elems->pushBackSilent(ielem);
2841 return elems.retn();
2845 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2846 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2847 * added in 'elems' parameter.
2849 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2851 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2852 if(getMeshDimension()==-1)
2854 elems->pushBackSilent(0);
2855 return elems.retn();
2857 int dim=getSpaceDimension();
2858 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2859 const int* conn = getNodalConnectivity()->getConstPointer();
2860 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2861 const double* coords = getCoords()->getConstPointer();
2862 int nbOfCells=getNumberOfCells();
2863 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2865 for (int i=0; i<dim; i++)
2867 elem_bb[i*2]=std::numeric_limits<double>::max();
2868 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2871 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2873 int node= conn[inode];
2874 if(node>=0)//avoid polyhedron separator
2876 for (int idim=0; idim<dim; idim++)
2878 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2880 elem_bb[idim*2] = coords[node*dim+idim] ;
2882 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2884 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2889 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2890 elems->pushBackSilent(ielem);
2892 return elems.retn();
2896 * Returns a type of a cell by its id.
2897 * \param [in] cellId - the id of the cell of interest.
2898 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2899 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2901 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2903 const int *ptI=_nodal_connec_index->getConstPointer();
2904 const int *pt=_nodal_connec->getConstPointer();
2905 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2906 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2909 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2910 throw INTERP_KERNEL::Exception(oss.str().c_str());
2915 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2916 * This method does not throw exception if geometric type \a type is not in \a this.
2917 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2918 * The coordinates array is not considered here.
2920 * \param [in] type the geometric type
2921 * \return cell ids in this having geometric type \a type.
2923 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2928 checkConnectivityFullyDefined();
2929 int nbCells=getNumberOfCells();
2930 int mdim=getMeshDimension();
2931 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2932 if(mdim!=(int)cm.getDimension())
2933 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2934 const int *ptI=_nodal_connec_index->getConstPointer();
2935 const int *pt=_nodal_connec->getConstPointer();
2936 for(int i=0;i<nbCells;i++)
2938 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2939 ret->pushBackSilent(i);
2945 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2947 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2949 const int *ptI=_nodal_connec_index->getConstPointer();
2950 const int *pt=_nodal_connec->getConstPointer();
2951 int nbOfCells=getNumberOfCells();
2953 for(int i=0;i<nbOfCells;i++)
2954 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2960 * Returns the nodal connectivity of a given cell.
2961 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2962 * all returned node ids can be used in getCoordinatesOfNode().
2963 * \param [in] cellId - an id of the cell of interest.
2964 * \param [in,out] conn - a vector where the node ids are appended. It is not
2965 * cleared before the appending.
2966 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2968 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2970 const int *ptI=_nodal_connec_index->getConstPointer();
2971 const int *pt=_nodal_connec->getConstPointer();
2972 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2977 std::string MEDCouplingUMesh::simpleRepr() const
2979 static const char msg0[]="No coordinates specified !";
2980 std::ostringstream ret;
2981 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2982 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2984 double tt=getTime(tmpp1,tmpp2);
2985 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2986 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2988 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2990 { ret << " Mesh dimension has not been set or is invalid !"; }
2993 const int spaceDim=getSpaceDimension();
2994 ret << spaceDim << "\nInfo attached on space dimension : ";
2995 for(int i=0;i<spaceDim;i++)
2996 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3000 ret << msg0 << "\n";
3001 ret << "Number of nodes : ";
3003 ret << getNumberOfNodes() << "\n";
3005 ret << msg0 << "\n";
3006 ret << "Number of cells : ";
3007 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3008 ret << getNumberOfCells() << "\n";
3010 ret << "No connectivity specified !" << "\n";
3011 ret << "Cell types present : ";
3012 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3014 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3015 ret << cm.getRepr() << " ";
3021 std::string MEDCouplingUMesh::advancedRepr() const
3023 std::ostringstream ret;
3024 ret << simpleRepr();
3025 ret << "\nCoordinates array : \n___________________\n\n";
3027 _coords->reprWithoutNameStream(ret);
3029 ret << "No array set !\n";
3030 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3031 reprConnectivityOfThisLL(ret);
3036 * This method returns a C++ code that is a dump of \a this.
3037 * This method will throw if this is not fully defined.
3039 std::string MEDCouplingUMesh::cppRepr() const
3041 static const char coordsName[]="coords";
3042 static const char connName[]="conn";
3043 static const char connIName[]="connI";
3044 checkFullyDefined();
3045 std::ostringstream ret; ret << "// coordinates" << std::endl;
3046 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3047 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3048 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3049 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3050 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3051 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3052 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3056 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3058 std::ostringstream ret;
3059 reprConnectivityOfThisLL(ret);
3064 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3065 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3066 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3069 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3070 * 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
3071 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3073 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3075 int mdim=getMeshDimension();
3077 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3078 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3080 bool needToCpyCT=true;
3083 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3091 if(!_nodal_connec_index)
3093 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3098 tmp2=_nodal_connec_index;
3101 ret->setConnectivity(tmp1,tmp2,false);
3106 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3107 ret->setCoords(coords);
3110 ret->setCoords(_coords);
3114 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3116 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3118 int nbOfCells=getNumberOfCells();
3119 const int *c=_nodal_connec->getConstPointer();
3120 const int *ci=_nodal_connec_index->getConstPointer();
3121 for(int i=0;i<nbOfCells;i++)
3123 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3124 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3125 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3130 stream << "Connectivity not defined !\n";
3133 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3135 const int *ptI=_nodal_connec_index->getConstPointer();
3136 const int *pt=_nodal_connec->getConstPointer();
3137 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3138 return ptI[cellId+1]-ptI[cellId]-1;
3140 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3144 * Returns types of cells of the specified part of \a this mesh.
3145 * This method avoids computing sub-mesh explicitely to get its types.
3146 * \param [in] begin - an array of cell ids of interest.
3147 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3148 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3149 * describing the cell types.
3150 * \throw If the coordinates array is not set.
3151 * \throw If the nodal connectivity of cells is not defined.
3152 * \sa getAllGeoTypes()
3154 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3156 checkFullyDefined();
3157 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3158 const int *conn=_nodal_connec->getConstPointer();
3159 const int *connIndex=_nodal_connec_index->getConstPointer();
3160 for(const int *w=begin;w!=end;w++)
3161 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3166 * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3167 * Optionally updates
3168 * a set of types of cells constituting \a this mesh.
3169 * This method is for advanced users having prepared their connectivity before. For
3170 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3171 * \param [in] conn - the nodal connectivity array.
3172 * \param [in] connIndex - the nodal connectivity index array.
3173 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3176 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3178 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3179 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3180 if(isComputingTypes)
3186 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3187 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3189 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3190 _nodal_connec(0),_nodal_connec_index(0),
3191 _types(other._types)
3193 if(other._nodal_connec)
3194 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3195 if(other._nodal_connec_index)
3196 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3199 MEDCouplingUMesh::~MEDCouplingUMesh()
3202 _nodal_connec->decrRef();
3203 if(_nodal_connec_index)
3204 _nodal_connec_index->decrRef();
3208 * Recomputes a set of cell types of \a this mesh. For more info see
3209 * \ref MEDCouplingUMeshNodalConnectivity.
3211 void MEDCouplingUMesh::computeTypes()
3213 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3217 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3219 void MEDCouplingUMesh::checkFullyDefined() const
3221 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3222 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3226 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3228 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3230 if(!_nodal_connec_index || !_nodal_connec)
3231 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3235 * Returns a number of cells constituting \a this mesh.
3236 * \return int - the number of cells in \a this mesh.
3237 * \throw If the nodal connectivity of cells is not defined.
3239 int MEDCouplingUMesh::getNumberOfCells() const
3241 if(_nodal_connec_index)
3242 return _nodal_connec_index->getNumberOfTuples()-1;
3247 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3251 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3252 * mesh. For more info see \ref meshes.
3253 * \return int - the dimension of \a this mesh.
3254 * \throw If the mesh dimension is not defined using setMeshDimension().
3256 int MEDCouplingUMesh::getMeshDimension() const
3259 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3264 * Returns a length of the nodal connectivity array.
3265 * This method is for test reason. Normally the integer returned is not useable by
3266 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3267 * \return int - the length of the nodal connectivity array.
3269 int MEDCouplingUMesh::getMeshLength() const
3271 return _nodal_connec->getNbOfElems();
3275 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3277 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3279 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3280 tinyInfo.push_back(getMeshDimension());
3281 tinyInfo.push_back(getNumberOfCells());
3283 tinyInfo.push_back(getMeshLength());
3285 tinyInfo.push_back(-1);
3289 * First step of unserialization process.
3291 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3293 return tinyInfo[6]<=0;
3297 * Second step of serialization process.
3298 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3301 * \param littleStrings
3303 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3305 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3307 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3311 * Third and final step of serialization process.
3313 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3315 MEDCouplingPointSet::serialize(a1,a2);
3316 if(getMeshDimension()>-1)
3318 a1=DataArrayInt::New();
3319 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3320 int *ptA1=a1->getPointer();
3321 const int *conn=getNodalConnectivity()->getConstPointer();
3322 const int *index=getNodalConnectivityIndex()->getConstPointer();
3323 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3324 std::copy(conn,conn+getMeshLength(),ptA1);
3331 * Second and final unserialization process.
3332 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3334 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3336 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3337 setMeshDimension(tinyInfo[5]);
3341 const int *recvBuffer=a1->getConstPointer();
3342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3343 myConnecIndex->alloc(tinyInfo[6]+1,1);
3344 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3346 myConnec->alloc(tinyInfo[7],1);
3347 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3348 setConnectivity(myConnec, myConnecIndex);
3353 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3354 * CellIds are given using range specified by a start an end and step.
3356 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3358 checkFullyDefined();
3359 int ncell=getNumberOfCells();
3360 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3361 ret->_mesh_dim=_mesh_dim;
3362 ret->setCoords(_coords);
3363 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3365 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3367 const int *conn=_nodal_connec->getConstPointer();
3368 const int *connIndex=_nodal_connec_index->getConstPointer();
3369 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3371 if(work>=0 && work<ncell)
3373 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3377 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3378 throw INTERP_KERNEL::Exception(oss.str().c_str());
3381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3382 int *newConnPtr=newConn->getPointer();
3383 std::set<INTERP_KERNEL::NormalizedCellType> types;
3385 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3387 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3388 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3390 ret->setConnectivity(newConn,newConnI,false);
3392 ret->copyTinyInfoFrom(this);
3397 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3398 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3399 * The return newly allocated mesh will share the same coordinates as \a this.
3401 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3403 checkConnectivityFullyDefined();
3404 int ncell=getNumberOfCells();
3405 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3406 ret->_mesh_dim=_mesh_dim;
3407 ret->setCoords(_coords);
3408 std::size_t nbOfElemsRet=std::distance(begin,end);
3409 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3411 const int *conn=_nodal_connec->getConstPointer();
3412 const int *connIndex=_nodal_connec_index->getConstPointer();
3414 for(const int *work=begin;work!=end;work++,newNbring++)
3416 if(*work>=0 && *work<ncell)
3417 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3421 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3422 throw INTERP_KERNEL::Exception(oss.str().c_str());
3425 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3426 int *connRetWork=connRet;
3427 std::set<INTERP_KERNEL::NormalizedCellType> types;
3428 for(const int *work=begin;work!=end;work++)
3430 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3431 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3434 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3436 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3437 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3439 ret->copyTinyInfoFrom(this);
3444 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3446 * For 1D cells, the returned field contains lengths.<br>
3447 * For 2D cells, the returned field contains areas.<br>
3448 * For 3D cells, the returned field contains volumes.
3449 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3450 * orientation, i.e. the volume is always positive.
3451 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3452 * and one time . The caller is to delete this field using decrRef() as it is no
3455 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3457 std::string name="MeasureOfMesh_";
3459 int nbelem=getNumberOfCells();
3460 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3461 field->setName(name);
3462 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3463 array->alloc(nbelem,1);
3464 double *area_vol=array->getPointer();
3465 field->setArray(array) ; array=0;
3466 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3467 field->synchronizeTimeWithMesh();
3468 if(getMeshDimension()!=-1)
3471 INTERP_KERNEL::NormalizedCellType type;
3472 int dim_space=getSpaceDimension();
3473 const double *coords=getCoords()->getConstPointer();
3474 const int *connec=getNodalConnectivity()->getConstPointer();
3475 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3476 for(int iel=0;iel<nbelem;iel++)
3478 ipt=connec_index[iel];
3479 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3480 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);
3483 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3487 area_vol[0]=std::numeric_limits<double>::max();
3489 return field.retn();
3493 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3495 * For 1D cells, the returned array contains lengths.<br>
3496 * For 2D cells, the returned array contains areas.<br>
3497 * For 3D cells, the returned array contains volumes.
3498 * This method avoids building explicitly a part of \a this mesh to perform the work.
3499 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3500 * orientation, i.e. the volume is always positive.
3501 * \param [in] begin - an array of cell ids of interest.
3502 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3503 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3504 * delete this array using decrRef() as it is no more needed.
3506 * \if ENABLE_EXAMPLES
3507 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3508 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3510 * \sa getMeasureField()
3512 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3514 std::string name="PartMeasureOfMesh_";
3516 int nbelem=(int)std::distance(begin,end);
3517 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3518 array->setName(name);
3519 array->alloc(nbelem,1);
3520 double *area_vol=array->getPointer();
3521 if(getMeshDimension()!=-1)
3524 INTERP_KERNEL::NormalizedCellType type;
3525 int dim_space=getSpaceDimension();
3526 const double *coords=getCoords()->getConstPointer();
3527 const int *connec=getNodalConnectivity()->getConstPointer();
3528 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3529 for(const int *iel=begin;iel!=end;iel++)
3531 ipt=connec_index[*iel];
3532 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3533 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3536 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3540 area_vol[0]=std::numeric_limits<double>::max();
3542 return array.retn();
3546 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3547 * \a this one. The returned field contains the dual cell volume for each corresponding
3548 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3549 * the dual mesh in P1 sens of \a this.<br>
3550 * For 1D cells, the returned field contains lengths.<br>
3551 * For 2D cells, the returned field contains areas.<br>
3552 * For 3D cells, the returned field contains volumes.
3553 * This method is useful to check "P1*" conservative interpolators.
3554 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3555 * orientation, i.e. the volume is always positive.
3556 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3557 * nodes and one time. The caller is to delete this array using decrRef() as
3558 * it is no more needed.
3560 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3562 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3563 std::string name="MeasureOnNodeOfMesh_";
3565 int nbNodes=getNumberOfNodes();
3566 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3567 double cst=1./((double)getMeshDimension()+1.);
3568 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3569 array->alloc(nbNodes,1);
3570 double *valsToFill=array->getPointer();
3571 std::fill(valsToFill,valsToFill+nbNodes,0.);
3572 const double *values=tmp->getArray()->getConstPointer();
3573 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3574 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3575 getReverseNodalConnectivity(da,daInd);
3576 const int *daPtr=da->getConstPointer();
3577 const int *daIPtr=daInd->getConstPointer();
3578 for(int i=0;i<nbNodes;i++)
3579 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3580 valsToFill[i]+=cst*values[*cell];
3582 ret->setArray(array);
3587 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3588 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3589 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3590 * and are normalized.
3591 * <br> \a this can be either
3592 * - a 2D mesh in 2D or 3D space or
3593 * - an 1D mesh in 2D space.
3595 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3596 * cells and one time. The caller is to delete this field using decrRef() as
3597 * it is no more needed.
3598 * \throw If the nodal connectivity of cells is not defined.
3599 * \throw If the coordinates array is not set.
3600 * \throw If the mesh dimension is not set.
3601 * \throw If the mesh and space dimension is not as specified above.
3603 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3605 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3606 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3607 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3608 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3609 int nbOfCells=getNumberOfCells();
3610 int nbComp=getMeshDimension()+1;
3611 array->alloc(nbOfCells,nbComp);
3612 double *vals=array->getPointer();
3613 const int *connI=_nodal_connec_index->getConstPointer();
3614 const int *conn=_nodal_connec->getConstPointer();
3615 const double *coords=_coords->getConstPointer();
3616 if(getMeshDimension()==2)
3618 if(getSpaceDimension()==3)
3620 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3621 const double *locPtr=loc->getConstPointer();
3622 for(int i=0;i<nbOfCells;i++,vals+=3)
3624 int offset=connI[i];
3625 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3626 double n=INTERP_KERNEL::norm<3>(vals);
3627 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3632 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3633 const double *isAbsPtr=isAbs->getArray()->begin();
3634 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3635 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3638 else//meshdimension==1
3641 for(int i=0;i<nbOfCells;i++)
3643 int offset=connI[i];
3644 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3645 double n=INTERP_KERNEL::norm<2>(tmp);
3646 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3651 ret->setArray(array);
3653 ret->synchronizeTimeWithSupport();
3658 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3659 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3660 * and are normalized.
3661 * <br> \a this can be either
3662 * - a 2D mesh in 2D or 3D space or
3663 * - an 1D mesh in 2D space.
3665 * This method avoids building explicitly a part of \a this mesh to perform the work.
3666 * \param [in] begin - an array of cell ids of interest.
3667 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3668 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3669 * cells and one time. The caller is to delete this field using decrRef() as
3670 * it is no more needed.
3671 * \throw If the nodal connectivity of cells is not defined.
3672 * \throw If the coordinates array is not set.
3673 * \throw If the mesh dimension is not set.
3674 * \throw If the mesh and space dimension is not as specified above.
3675 * \sa buildOrthogonalField()
3677 * \if ENABLE_EXAMPLES
3678 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3679 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3682 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3684 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3685 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3686 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3687 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3688 std::size_t nbelems=std::distance(begin,end);
3689 int nbComp=getMeshDimension()+1;
3690 array->alloc((int)nbelems,nbComp);
3691 double *vals=array->getPointer();
3692 const int *connI=_nodal_connec_index->getConstPointer();
3693 const int *conn=_nodal_connec->getConstPointer();
3694 const double *coords=_coords->getConstPointer();
3695 if(getMeshDimension()==2)
3697 if(getSpaceDimension()==3)
3699 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3700 const double *locPtr=loc->getConstPointer();
3701 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3703 int offset=connI[*i];
3704 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3705 double n=INTERP_KERNEL::norm<3>(vals);
3706 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3711 for(std::size_t i=0;i<nbelems;i++)
3712 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3715 else//meshdimension==1
3718 for(const int *i=begin;i!=end;i++)
3720 int offset=connI[*i];
3721 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3722 double n=INTERP_KERNEL::norm<2>(tmp);
3723 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3728 ret->setArray(array);
3730 ret->synchronizeTimeWithSupport();
3735 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3736 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3737 * and are \b not normalized.
3738 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3739 * cells and one time. The caller is to delete this field using decrRef() as
3740 * it is no more needed.
3741 * \throw If the nodal connectivity of cells is not defined.
3742 * \throw If the coordinates array is not set.
3743 * \throw If \a this->getMeshDimension() != 1.
3744 * \throw If \a this mesh includes cells of type other than SEG2.
3746 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3748 if(getMeshDimension()!=1)
3749 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3750 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3751 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3752 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3753 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3754 int nbOfCells=getNumberOfCells();
3755 int spaceDim=getSpaceDimension();
3756 array->alloc(nbOfCells,spaceDim);
3757 double *pt=array->getPointer();
3758 const double *coo=getCoords()->getConstPointer();
3759 std::vector<int> conn;
3761 for(int i=0;i<nbOfCells;i++)
3764 getNodeIdsOfCell(i,conn);
3765 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3767 ret->setArray(array);
3769 ret->synchronizeTimeWithSupport();
3774 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3775 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3776 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3777 * from. If a result face is shared by two 3D cells, then the face in included twice in
3779 * \param [in] origin - 3 components of a point defining location of the plane.
3780 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3781 * must be greater than 1e-6.
3782 * \param [in] eps - half-thickness of the plane.
3783 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3784 * producing correspondent 2D cells. The caller is to delete this array
3785 * using decrRef() as it is no more needed.
3786 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3787 * not share the node coordinates array with \a this mesh. The caller is to
3788 * delete this mesh using decrRef() as it is no more needed.
3789 * \throw If the coordinates array is not set.
3790 * \throw If the nodal connectivity of cells is not defined.
3791 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3792 * \throw If magnitude of \a vec is less than 1e-6.
3793 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3794 * \throw If \a this includes quadratic cells.
3796 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3798 checkFullyDefined();
3799 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3800 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3801 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3802 if(candidates->empty())
3803 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3804 std::vector<int> nodes;
3805 DataArrayInt *cellIds1D=0;
3806 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3807 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3812 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3813 revDesc2=0; revDescIndx2=0;
3814 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3815 revDesc1=0; revDescIndx1=0;
3816 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3819 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3820 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3822 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3823 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3824 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3825 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3826 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3827 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3828 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3829 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3830 if(cellIds2->empty())
3831 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3832 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3833 ret->setCoords(mDesc1->getCoords());
3834 ret->setConnectivity(conn,connI,true);
3835 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3840 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3841 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
3842 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3844 * \param [in] origin - 3 components of a point defining location of the plane.
3845 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3846 * must be greater than 1e-6.
3847 * \param [in] eps - half-thickness of the plane.
3848 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3849 * producing correspondent segments. The caller is to delete this array
3850 * using decrRef() as it is no more needed.
3851 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3852 * mesh in 3D space. This mesh does not share the node coordinates array with
3853 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3855 * \throw If the coordinates array is not set.
3856 * \throw If the nodal connectivity of cells is not defined.
3857 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3858 * \throw If magnitude of \a vec is less than 1e-6.
3859 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3860 * \throw If \a this includes quadratic cells.
3862 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3864 checkFullyDefined();
3865 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3866 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3867 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3868 if(candidates->empty())
3869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3870 std::vector<int> nodes;
3871 DataArrayInt *cellIds1D=0;
3872 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3873 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3874 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3878 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3879 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3882 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3883 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3885 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3886 int ncellsSub=subMesh->getNumberOfCells();
3887 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3888 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3889 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3890 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3891 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3893 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3894 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3895 for(int i=0;i<ncellsSub;i++)
3897 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3899 if(cut3DSurf[i].first!=-2)
3901 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3902 connI->pushBackSilent(conn->getNumberOfTuples());
3903 cellIds2->pushBackSilent(i);
3907 int cellId3DSurf=cut3DSurf[i].second;
3908 int offset=nodalI[cellId3DSurf]+1;
3909 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3910 for(int j=0;j<nbOfEdges;j++)
3912 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3913 connI->pushBackSilent(conn->getNumberOfTuples());
3914 cellIds2->pushBackSilent(cellId3DSurf);
3919 if(cellIds2->empty())
3920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3921 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3922 ret->setCoords(mDesc1->getCoords());
3923 ret->setConnectivity(conn,connI,true);
3924 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3929 * Finds cells whose bounding boxes intersect a given plane.
3930 * \param [in] origin - 3 components of a point defining location of the plane.
3931 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3932 * must be greater than 1e-6.
3933 * \param [in] eps - half-thickness of the plane.
3934 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3935 * cells. The caller is to delete this array using decrRef() as it is no more
3937 * \throw If the coordinates array is not set.
3938 * \throw If the nodal connectivity of cells is not defined.
3939 * \throw If \a this->getSpaceDimension() != 3.
3940 * \throw If magnitude of \a vec is less than 1e-6.
3941 * \sa buildSlice3D()
3943 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3945 checkFullyDefined();
3946 if(getSpaceDimension()!=3)
3947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3948 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3950 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3952 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3953 double angle=acos(vec[2]/normm);
3954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3958 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3959 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3960 if(normm2/normm>1e-6)
3961 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3964 mw->getBoundingBox(bbox);
3965 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3966 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3970 getBoundingBox(bbox);
3971 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3972 cellIds=getCellsInBoundingBox(bbox,eps);
3974 return cellIds.retn();
3978 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3979 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3980 * No consideration of coordinate is done by this method.
3981 * 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)
3982 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3984 bool MEDCouplingUMesh::isContiguous1D() const
3986 if(getMeshDimension()!=1)
3987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3988 int nbCells=getNumberOfCells();
3990 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3991 const int *connI=_nodal_connec_index->getConstPointer();
3992 const int *conn=_nodal_connec->getConstPointer();
3993 int ref=conn[connI[0]+2];
3994 for(int i=1;i<nbCells;i++)
3996 if(conn[connI[i]+1]!=ref)
3998 ref=conn[connI[i]+2];
4004 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4005 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4006 * \param pt reference point of the line
4007 * \param v normalized director vector of the line
4008 * \param eps max precision before throwing an exception
4009 * \param res output of size this->getNumberOfCells
4011 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4013 if(getMeshDimension()!=1)
4014 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4015 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4016 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4017 if(getSpaceDimension()!=3)
4018 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4019 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4020 const double *fPtr=f->getArray()->getConstPointer();
4022 for(int i=0;i<getNumberOfCells();i++)
4024 const double *tmp1=fPtr+3*i;
4025 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4026 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4027 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4028 double n1=INTERP_KERNEL::norm<3>(tmp);
4029 n1/=INTERP_KERNEL::norm<3>(tmp1);
4031 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4033 const double *coo=getCoords()->getConstPointer();
4034 for(int i=0;i<getNumberOfNodes();i++)
4036 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4037 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4038 res[i]=std::accumulate(tmp,tmp+3,0.);
4043 * 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.
4044 * \a this is expected to be a mesh so that its space dimension is equal to its
4045 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4046 * 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).
4048 * 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
4049 * 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).
4050 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4052 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4053 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4055 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4056 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4057 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4058 * \return the positive value of the distance.
4059 * \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
4061 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4063 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4065 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4066 if(meshDim!=spaceDim-1)
4067 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4068 if(meshDim!=2 && meshDim!=1)
4069 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4070 checkFullyDefined();
4071 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4072 { 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()); }
4073 DataArrayInt *ret1=0;
4074 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4075 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4077 cellId=*ret1Safe->begin();
4078 return *ret0->begin();
4082 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4083 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4084 * 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
4085 * 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).
4086 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4088 * \a this is expected to be a mesh so that its space dimension is equal to its
4089 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4090 * 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).
4092 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4093 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4095 * \param [in] pts the list of points in which each tuple represents a point
4096 * \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.
4097 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4098 * \throw if number of components of \a pts is not equal to the space dimension.
4099 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4100 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4102 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4105 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4106 pts->checkAllocated();
4107 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4108 if(meshDim!=spaceDim-1)
4109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4110 if(meshDim!=2 && meshDim!=1)
4111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4112 if(pts->getNumberOfComponents()!=spaceDim)
4114 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4115 throw INTERP_KERNEL::Exception(oss.str().c_str());
4117 checkFullyDefined();
4118 int nbCells=getNumberOfCells();
4120 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4121 int nbOfPts=pts->getNumberOfTuples();
4122 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4124 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4125 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4126 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4127 const double *bbox(bboxArr->begin());
4132 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4133 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4135 double x=std::numeric_limits<double>::max();
4136 std::vector<int> elems;
4137 myTree.getMinDistanceOfMax(ptsPtr,x);
4138 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4139 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4145 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4146 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4148 double x=std::numeric_limits<double>::max();
4149 std::vector<int> elems;
4150 myTree.getMinDistanceOfMax(ptsPtr,x);
4151 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4152 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4157 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4159 cellIds=ret1.retn();
4164 * \param [in] pt the start pointer (included) of the coordinates of the point
4165 * \param [in] cellIdsBg the start pointer (included) of cellIds
4166 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4167 * \param [in] nc nodal connectivity
4168 * \param [in] ncI nodal connectivity index
4169 * \param [in,out] ret0 the min distance between \a this and the external input point
4170 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4171 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4173 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)
4176 ret0=std::numeric_limits<double>::max();
4177 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4179 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4181 case INTERP_KERNEL::NORM_TRI3:
4183 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4185 { ret0=tmp; cellId=*zeCell; }
4188 case INTERP_KERNEL::NORM_QUAD4:
4189 case INTERP_KERNEL::NORM_POLYGON:
4191 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4193 { ret0=tmp; cellId=*zeCell; }
4197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4203 * \param [in] pt the start pointer (included) of the coordinates of the point
4204 * \param [in] cellIdsBg the start pointer (included) of cellIds
4205 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4206 * \param [in] nc nodal connectivity
4207 * \param [in] ncI nodal connectivity index
4208 * \param [in,out] ret0 the min distance between \a this and the external input point
4209 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4210 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4212 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)
4215 ret0=std::numeric_limits<double>::max();
4216 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4218 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4220 case INTERP_KERNEL::NORM_SEG2:
4222 std::size_t uselessEntry=0;
4223 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4226 { ret0=tmp; cellId=*zeCell; }
4230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4236 * Finds cells in contact with a ball (i.e. a point with precision).
4237 * 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.
4238 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4240 * \warning This method is suitable if the caller intends to evaluate only one
4241 * point, for more points getCellsContainingPoints() is recommended as it is
4243 * \param [in] pos - array of coordinates of the ball central point.
4244 * \param [in] eps - ball radius.
4245 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4246 * if there are no such cells.
4247 * \throw If the coordinates array is not set.
4248 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4250 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4252 std::vector<int> elts;
4253 getCellsContainingPoint(pos,eps,elts);
4256 return elts.front();
4260 * Finds cells in contact with a ball (i.e. a point with precision).
4261 * 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.
4262 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4263 * \warning This method is suitable if the caller intends to evaluate only one
4264 * point, for more points getCellsContainingPoints() is recommended as it is
4266 * \param [in] pos - array of coordinates of the ball central point.
4267 * \param [in] eps - ball radius.
4268 * \param [out] elts - vector returning ids of the found cells. It is cleared
4269 * before inserting ids.
4270 * \throw If the coordinates array is not set.
4271 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4273 * \if ENABLE_EXAMPLES
4274 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4275 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4278 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4281 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4282 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4287 namespace ParaMEDMEM
4289 template<const int SPACEDIMM>
4293 static const int MY_SPACEDIM=SPACEDIMM;
4294 static const int MY_MESHDIM=8;
4295 typedef int MyConnType;
4296 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4298 // useless, but for windows compilation ...
4299 const double* getCoordinatesPtr() const { return 0; }
4300 const int* getConnectivityPtr() const { return 0; }
4301 const int* getConnectivityIndexPtr() const { return 0; }
4302 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4306 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4308 INTERP_KERNEL::Edge *ret(0);
4309 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]));
4310 m[n0]=bg[0]; m[n1]=bg[1];
4313 case INTERP_KERNEL::NORM_SEG2:
4315 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4318 case INTERP_KERNEL::NORM_SEG3:
4320 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4321 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4322 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4323 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4324 bool colinearity(inters.areColinears());
4325 delete e1; delete e2;
4327 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4329 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4333 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4338 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4340 INTERP_KERNEL::Edge *ret=0;
4343 case INTERP_KERNEL::NORM_SEG2:
4345 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4348 case INTERP_KERNEL::NORM_SEG3:
4350 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4351 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4352 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4353 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4354 bool colinearity=inters.areColinears();
4355 delete e1; delete e2;
4357 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4359 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4360 mapp2[bg[2]].second=false;
4364 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4370 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4371 * the global mesh 'mDesc'.
4372 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4373 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4375 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4376 std::map<INTERP_KERNEL::Node *,int>& mapp)
4379 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.
4380 const double *coo=mDesc->getCoords()->getConstPointer();
4381 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4382 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4384 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4385 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4386 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4388 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4389 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4391 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4392 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4394 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4395 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4397 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4399 if((*it2).second.second)
4400 mapp[(*it2).second.first]=(*it2).first;
4401 ((*it2).second.first)->decrRef();
4406 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4410 int locId=nodeId-offset2;
4411 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4415 int locId=nodeId-offset1;
4416 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4418 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4422 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4424 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4425 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4426 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4428 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4430 int eltId1=abs(*desc1)-1;
4431 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4433 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4434 if(it==mappRev.end())
4436 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4447 template<int SPACEDIM>
4448 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4449 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4451 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4452 int *eltsIndexPtr(eltsIndex->getPointer());
4453 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4454 const double *bbox(bboxArr->begin());
4455 int nbOfCells=getNumberOfCells();
4456 const int *conn=_nodal_connec->getConstPointer();
4457 const int *connI=_nodal_connec_index->getConstPointer();
4458 double bb[2*SPACEDIM];
4459 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4460 for(int i=0;i<nbOfPoints;i++)
4462 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4463 for(int j=0;j<SPACEDIM;j++)
4465 bb[2*j]=pos[SPACEDIM*i+j];
4466 bb[2*j+1]=pos[SPACEDIM*i+j];
4468 std::vector<int> candidates;
4469 myTree.getIntersectingElems(bb,candidates);
4470 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4472 int sz(connI[(*iter)+1]-connI[*iter]-1);
4473 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4475 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4476 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4480 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4481 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4482 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4483 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4484 INTERP_KERNEL::QuadraticPolygon *pol(0);
4485 for(int j=0;j<sz;j++)
4487 int nodeId(conn[connI[*iter]+1+j]);
4488 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4490 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4491 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4493 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4494 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4495 double a(0.),b(0.),c(0.);
4496 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4497 status=pol->isInOrOut2(n);
4498 delete pol; n->decrRef();
4502 eltsIndexPtr[i+1]++;
4503 elts->pushBackSilent(*iter);
4509 * Finds cells in contact with several balls (i.e. points with precision).
4510 * This method is an extension of getCellContainingPoint() and
4511 * getCellsContainingPoint() for the case of multiple points.
4512 * 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.
4513 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4514 * \param [in] pos - an array of coordinates of points in full interlace mode :
4515 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4516 * this->getSpaceDimension() * \a nbOfPoints
4517 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4518 * \param [in] eps - radius of balls (i.e. the precision).
4519 * \param [out] elts - vector returning ids of found cells.
4520 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4521 * dividing cell ids in \a elts into groups each referring to one
4522 * point. Its every element (except the last one) is an index pointing to the
4523 * first id of a group of cells. For example cells in contact with the *i*-th
4524 * point are described by following range of indices:
4525 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4526 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4527 * Number of cells in contact with the *i*-th point is
4528 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4529 * \throw If the coordinates array is not set.
4530 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4532 * \if ENABLE_EXAMPLES
4533 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4534 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4537 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4540 int spaceDim=getSpaceDimension();
4541 int mDim=getMeshDimension();
4546 const double *coords=_coords->getConstPointer();
4547 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4554 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4556 else if(spaceDim==2)
4560 const double *coords=_coords->getConstPointer();
4561 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4564 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4566 else if(spaceDim==1)
4570 const double *coords=_coords->getConstPointer();
4571 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4574 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4577 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4581 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4582 * least two its edges intersect each other anywhere except their extremities. An
4583 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4584 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4585 * cleared before filling in.
4586 * \param [in] eps - precision.
4587 * \throw If \a this->getMeshDimension() != 2.
4588 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4590 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4592 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4593 if(getMeshDimension()!=2)
4594 throw INTERP_KERNEL::Exception(msg);
4595 int spaceDim=getSpaceDimension();
4596 if(spaceDim!=2 && spaceDim!=3)
4597 throw INTERP_KERNEL::Exception(msg);
4598 const int *conn=_nodal_connec->getConstPointer();
4599 const int *connI=_nodal_connec_index->getConstPointer();
4600 int nbOfCells=getNumberOfCells();
4601 std::vector<double> cell2DinS2;
4602 for(int i=0;i<nbOfCells;i++)
4604 int offset=connI[i];
4605 int nbOfNodesForCell=connI[i+1]-offset-1;
4606 if(nbOfNodesForCell<=3)
4608 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4609 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4610 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4617 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4619 * 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.
4620 * 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.
4622 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4623 * This convex envelop is computed using Jarvis march algorithm.
4624 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4625 * 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)
4626 * 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.
4628 * \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.
4629 * \sa MEDCouplingUMesh::colinearize2D
4631 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4633 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4634 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4635 checkFullyDefined();
4636 const double *coords=getCoords()->getConstPointer();
4637 int nbOfCells=getNumberOfCells();
4638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4639 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4641 int *workIndexOut=nodalConnecIndexOut->getPointer();
4643 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4644 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4645 std::set<INTERP_KERNEL::NormalizedCellType> types;
4646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4647 isChanged->alloc(0,1);
4648 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4650 int pos=nodalConnecOut->getNumberOfTuples();
4651 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4652 isChanged->pushBackSilent(i);
4653 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4654 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4656 if(isChanged->empty())
4658 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4660 return isChanged.retn();
4664 * This method is \b NOT const because it can modify \a this.
4665 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4666 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4667 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4668 * \b 1 for translation and rotation around point of 'mesh1D'.
4669 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4671 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4673 checkFullyDefined();
4674 mesh1D->checkFullyDefined();
4675 if(!mesh1D->isContiguous1D())
4676 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4677 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4678 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4679 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4680 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4681 if(mesh1D->getMeshDimension()!=1)
4682 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4684 if(isPresenceOfQuadratic())
4686 if(mesh1D->isFullyQuadratic())
4689 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4691 int oldNbOfNodes(getNumberOfNodes());
4692 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4697 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4702 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4706 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4708 setCoords(newCoords);
4709 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4715 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4716 * If it is not the case an exception will be thrown.
4717 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4718 * intersection of plane defined by ('origin','vec').
4719 * This method has one in/out parameter : 'cut3DCurve'.
4720 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4721 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4722 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4723 * This method will throw an exception if \a this contains a non linear segment.
4725 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4727 checkFullyDefined();
4728 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4729 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4730 int ncells=getNumberOfCells();
4731 int nnodes=getNumberOfNodes();
4732 double vec2[3],vec3[3],vec4[3];
4733 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4735 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4736 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4737 const int *conn=_nodal_connec->getConstPointer();
4738 const int *connI=_nodal_connec_index->getConstPointer();
4739 const double *coo=_coords->getConstPointer();
4740 std::vector<double> addCoo;
4741 for(int i=0;i<ncells;i++)
4743 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4745 if(cut3DCurve[i]==-2)
4747 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4748 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];
4749 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4750 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4751 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4753 const double *st2=coo+3*st;
4754 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4755 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]));
4756 if(pos>eps && pos<1-eps)
4758 int nNode=((int)addCoo.size())/3;
4759 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4760 addCoo.insert(addCoo.end(),vec4,vec4+3);
4761 cut3DCurve[i]=nnodes+nNode;
4767 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4771 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4772 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4773 coo2->alloc(newNbOfNodes,3);
4774 double *tmp=coo2->getPointer();
4775 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4776 std::copy(addCoo.begin(),addCoo.end(),tmp);
4777 DataArrayDouble::SetArrayIn(coo2,_coords);
4782 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4783 * \param mesh1D is the input 1D mesh used for translation computation.
4784 * \return newCoords new coords filled by this method.
4786 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4788 int oldNbOfNodes=getNumberOfNodes();
4789 int nbOf1DCells=mesh1D->getNumberOfCells();
4790 int spaceDim=getSpaceDimension();
4791 DataArrayDouble *ret=DataArrayDouble::New();
4792 std::vector<bool> isQuads;
4793 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4794 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4795 double *retPtr=ret->getPointer();
4796 const double *coords=getCoords()->getConstPointer();
4797 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4799 std::vector<double> c;
4803 for(int i=0;i<nbOf1DCells;i++)
4806 mesh1D->getNodeIdsOfCell(i,v);
4808 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4809 mesh1D->getCoordinatesOfNode(v[0],c);
4810 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4811 for(int j=0;j<oldNbOfNodes;j++)
4812 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4816 mesh1D->getCoordinatesOfNode(v[1],c);
4817 mesh1D->getCoordinatesOfNode(v[0],c);
4818 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4819 for(int j=0;j<oldNbOfNodes;j++)
4820 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4823 ret->copyStringInfoFrom(*getCoords());
4828 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4829 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4830 * \return newCoords new coords filled by this method.
4832 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4834 if(mesh1D->getSpaceDimension()==2)
4835 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4836 if(mesh1D->getSpaceDimension()==3)
4837 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4838 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4842 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4843 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4844 * \return newCoords new coords filled by this method.
4846 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4850 int oldNbOfNodes=getNumberOfNodes();
4851 int nbOf1DCells=mesh1D->getNumberOfCells();
4853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4854 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4855 int nbOfLevsInVec=nbOf1DCells+1;
4856 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4857 double *retPtr=ret->getPointer();
4858 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4859 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4860 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4861 tmp->setCoords(tmp2);
4862 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4863 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4864 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4865 for(int i=1;i<nbOfLevsInVec;i++)
4867 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4868 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4869 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4870 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4871 tmp->translate(vec);
4872 double tmp3[2],radius,alpha,alpha0;
4873 const double *p0=i+1<nbOfLevsInVec?begin:third;
4874 const double *p1=i+1<nbOfLevsInVec?end:begin;
4875 const double *p2=i+1<nbOfLevsInVec?third:end;
4876 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4877 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]);
4878 double angle=acos(cosangle/(radius*radius));
4879 tmp->rotate(end,0,angle);
4880 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4886 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4887 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4888 * \return newCoords new coords filled by this method.
4890 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4893 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4894 int oldNbOfNodes=getNumberOfNodes();
4895 int nbOf1DCells=mesh1D->getNumberOfCells();
4897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4898 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4899 int nbOfLevsInVec=nbOf1DCells+1;
4900 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4901 double *retPtr=ret->getPointer();
4902 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4903 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4904 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4905 tmp->setCoords(tmp2);
4906 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4907 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4908 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4909 for(int i=1;i<nbOfLevsInVec;i++)
4911 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4912 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4913 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4914 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4915 tmp->translate(vec);
4916 double tmp3[2],radius,alpha,alpha0;
4917 const double *p0=i+1<nbOfLevsInVec?begin:third;
4918 const double *p1=i+1<nbOfLevsInVec?end:begin;
4919 const double *p2=i+1<nbOfLevsInVec?third:end;
4920 double vecPlane[3]={
4921 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4922 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4923 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4925 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4928 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4929 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4930 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4932 double c2=cos(asin(s2));
4934 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4935 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4936 {-vec2[1]*s2, vec2[0]*s2, c2}
4938 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]};
4939 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]};
4940 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]};
4941 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4942 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]);
4943 double angle=acos(cosangle/(radius*radius));
4944 tmp->rotate(end,vecPlane,angle);
4946 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4952 * This method is private because not easy to use for end user. This method is const contrary to
4953 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4954 * the coords sorted slice by slice.
4955 * \param isQuad specifies presence of quadratic cells.
4957 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4959 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4960 int nbOf2DCells(getNumberOfCells());
4961 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4962 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4963 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4965 newConnI->alloc(nbOf3DCells+1,1);
4966 int *newConnIPtr(newConnI->getPointer());
4968 std::vector<int> newc;
4969 for(int j=0;j<nbOf2DCells;j++)
4971 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4972 *newConnIPtr++=(int)newc.size();
4974 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4975 int *newConnPtr(newConn->getPointer());
4976 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4977 newConnIPtr=newConnI->getPointer();
4978 for(int iz=0;iz<nbOf1DCells;iz++)
4981 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4982 const int *posOfTypeOfCell(newConnIPtr);
4983 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4985 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4986 if(icell!=*posOfTypeOfCell)
4989 *newConnPtr=(*iter)+iz*deltaPerLev;
5000 ret->setConnectivity(newConn,newConnI,true);
5001 ret->setCoords(getCoords());
5006 * Checks if \a this mesh is constituted by only quadratic cells.
5007 * \return bool - \c true if there are only quadratic cells in \a this mesh.
5008 * \throw If the coordinates array is not set.
5009 * \throw If the nodal connectivity of cells is not defined.
5011 bool MEDCouplingUMesh::isFullyQuadratic() const
5013 checkFullyDefined();
5015 int nbOfCells=getNumberOfCells();
5016 for(int i=0;i<nbOfCells && ret;i++)
5018 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5019 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5020 ret=cm.isQuadratic();
5026 * Checks if \a this mesh includes any quadratic cell.
5027 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5028 * \throw If the coordinates array is not set.
5029 * \throw If the nodal connectivity of cells is not defined.
5031 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5033 checkFullyDefined();
5035 int nbOfCells=getNumberOfCells();
5036 for(int i=0;i<nbOfCells && !ret;i++)
5038 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5039 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5040 ret=cm.isQuadratic();
5046 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5047 * this mesh, it remains unchanged.
5048 * \throw If the coordinates array is not set.
5049 * \throw If the nodal connectivity of cells is not defined.
5051 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5053 checkFullyDefined();
5054 int nbOfCells=getNumberOfCells();
5056 const int *iciptr=_nodal_connec_index->getConstPointer();
5057 for(int i=0;i<nbOfCells;i++)
5059 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5060 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5061 if(cm.isQuadratic())
5063 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5064 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5065 if(!cml.isDynamic())
5066 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5068 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5073 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5075 const int *icptr=_nodal_connec->getConstPointer();
5076 newConn->alloc(getMeshLength()-delta,1);
5077 newConnI->alloc(nbOfCells+1,1);
5078 int *ocptr=newConn->getPointer();
5079 int *ociptr=newConnI->getPointer();
5082 for(int i=0;i<nbOfCells;i++,ociptr++)
5084 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5085 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5086 if(!cm.isQuadratic())
5088 _types.insert(type);
5089 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5090 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5094 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5095 _types.insert(typel);
5096 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5097 int newNbOfNodes=cml.getNumberOfNodes();
5099 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5100 *ocptr++=(int)typel;
5101 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5102 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5105 setConnectivity(newConn,newConnI,false);
5109 * This method converts all linear cell in \a this to quadratic one.
5110 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5111 * 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)
5112 * 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.
5113 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5114 * end of the existing coordinates.
5116 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5117 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5118 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5120 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5122 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5124 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5126 DataArrayInt *conn=0,*connI=0;
5127 DataArrayDouble *coords=0;
5128 std::set<INTERP_KERNEL::NormalizedCellType> types;
5129 checkFullyDefined();
5130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5131 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5132 int meshDim=getMeshDimension();
5133 switch(conversionType)
5139 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5140 connSafe=conn; connISafe=connI; coordsSafe=coords;
5143 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5144 connSafe=conn; connISafe=connI; coordsSafe=coords;
5147 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5148 connSafe=conn; connISafe=connI; coordsSafe=coords;
5151 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5159 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5160 connSafe=conn; connISafe=connI; coordsSafe=coords;
5163 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5164 connSafe=conn; connISafe=connI; coordsSafe=coords;
5167 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5168 connSafe=conn; connISafe=connI; coordsSafe=coords;
5171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5176 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5178 setConnectivity(connSafe,connISafe,false);
5180 setCoords(coordsSafe);
5186 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5187 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5188 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5189 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5190 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5191 * This method can be seen as the opposite method of colinearize2D.
5192 * 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
5193 * to avoid to modify the numbering of existing nodes.
5195 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5196 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5197 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5198 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5199 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5200 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5201 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5203 * \sa buildDescendingConnectivity2
5205 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5206 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5208 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5209 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5210 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5211 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5212 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5213 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5214 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5215 //DataArrayInt *out0(0),*outi0(0);
5216 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5217 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5218 //out0s=out0s->buildUnique(); out0s->sort(true);
5223 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5224 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5225 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5227 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5229 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5230 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5231 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5232 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5233 int nbOfCells=getNumberOfCells();
5234 int nbOfNodes=getNumberOfNodes();
5235 const int *cPtr=_nodal_connec->getConstPointer();
5236 const int *icPtr=_nodal_connec_index->getConstPointer();
5237 int lastVal=0,offset=nbOfNodes;
5238 for(int i=0;i<nbOfCells;i++,icPtr++)
5240 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5241 if(type==INTERP_KERNEL::NORM_SEG2)
5243 types.insert(INTERP_KERNEL::NORM_SEG3);
5244 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5245 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5246 newConn->pushBackSilent(offset++);
5248 newConnI->pushBackSilent(lastVal);
5249 ret->pushBackSilent(i);
5254 lastVal+=(icPtr[1]-icPtr[0]);
5255 newConnI->pushBackSilent(lastVal);
5256 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5259 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5260 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5264 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
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5270 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5271 DataArrayInt *conn1D=0,*conn1DI=0;
5272 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5273 DataArrayDouble *coordsTmp=0;
5274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5275 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5277 const int *c1DPtr=conn1D->begin();
5278 const int *c1DIPtr=conn1DI->begin();
5279 int nbOfCells=getNumberOfCells();
5280 const int *cPtr=_nodal_connec->getConstPointer();
5281 const int *icPtr=_nodal_connec_index->getConstPointer();
5283 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5285 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5286 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5287 if(!cm.isQuadratic())
5289 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5290 types.insert(typ2); newConn->pushBackSilent(typ2);
5291 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5292 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5293 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5294 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5295 newConnI->pushBackSilent(lastVal);
5296 ret->pushBackSilent(i);
5301 lastVal+=(icPtr[1]-icPtr[0]);
5302 newConnI->pushBackSilent(lastVal);
5303 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5306 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5311 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5312 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5313 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5315 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5318 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5319 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5322 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5324 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5325 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5331 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5332 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5333 DataArrayInt *conn1D=0,*conn1DI=0;
5334 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5335 DataArrayDouble *coordsTmp=0;
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5337 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5339 const int *c1DPtr=conn1D->begin();
5340 const int *c1DIPtr=conn1DI->begin();
5341 int nbOfCells=getNumberOfCells();
5342 const int *cPtr=_nodal_connec->getConstPointer();
5343 const int *icPtr=_nodal_connec_index->getConstPointer();
5344 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5345 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5347 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5348 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5349 if(!cm.isQuadratic())
5351 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5352 types.insert(typ2); newConn->pushBackSilent(typ2);
5353 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5354 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5355 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5356 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5357 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5358 newConnI->pushBackSilent(lastVal);
5359 ret->pushBackSilent(i);
5364 lastVal+=(icPtr[1]-icPtr[0]);
5365 newConnI->pushBackSilent(lastVal);
5366 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5369 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5370 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5375 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5376 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5377 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5379 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5382 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5383 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5386 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5389 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5391 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5397 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5398 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5399 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5400 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5401 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5404 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5406 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5408 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5409 int nbOfCells=getNumberOfCells();
5410 const int *cPtr=_nodal_connec->getConstPointer();
5411 const int *icPtr=_nodal_connec_index->getConstPointer();
5412 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5413 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5415 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5416 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5417 if(!cm.isQuadratic())
5419 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5420 if(typ2==INTERP_KERNEL::NORM_ERROR)
5422 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5423 throw INTERP_KERNEL::Exception(oss.str().c_str());
5425 types.insert(typ2); newConn->pushBackSilent(typ2);
5426 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5427 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5428 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5429 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5431 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5432 int tmpPos=newConn->getNumberOfTuples();
5433 newConn->pushBackSilent(nodeId2);
5434 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5436 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5437 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5438 newConnI->pushBackSilent(lastVal);
5439 ret->pushBackSilent(i);
5444 lastVal+=(icPtr[1]-icPtr[0]);
5445 newConnI->pushBackSilent(lastVal);
5446 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5451 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5452 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5453 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5454 int *c=newConn->getPointer();
5455 const int *cI(newConnI->begin());
5456 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5457 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5458 offset=coordsTmp2Safe->getNumberOfTuples();
5459 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5460 c[cI[(*elt)+1]-1]+=offset;
5461 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5466 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5467 * so that the number of cells remains the same. Quadratic faces are converted to
5468 * polygons. This method works only for 2D meshes in
5469 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5470 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5471 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5472 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5473 * a polylinized edge constituting the input polygon.
5474 * \throw If the coordinates array is not set.
5475 * \throw If the nodal connectivity of cells is not defined.
5476 * \throw If \a this->getMeshDimension() != 2.
5477 * \throw If \a this->getSpaceDimension() != 2.
5479 void MEDCouplingUMesh::tessellate2D(double eps)
5481 checkFullyDefined();
5482 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5483 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5484 double epsa=fabs(eps);
5485 if(epsa<std::numeric_limits<double>::min())
5486 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 !");
5487 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5489 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5491 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5492 revDesc1=0; revDescIndx1=0;
5493 mDesc->tessellate2DCurve(eps);
5494 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5495 setCoords(mDesc->getCoords());
5499 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5500 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5501 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5502 * a sub-divided edge.
5503 * \throw If the coordinates array is not set.
5504 * \throw If the nodal connectivity of cells is not defined.
5505 * \throw If \a this->getMeshDimension() != 1.
5506 * \throw If \a this->getSpaceDimension() != 2.
5508 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5510 checkFullyDefined();
5511 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5512 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5513 double epsa=fabs(eps);
5514 if(epsa<std::numeric_limits<double>::min())
5515 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 !");
5516 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5517 int nbCells=getNumberOfCells();
5518 int nbNodes=getNumberOfNodes();
5519 const int *conn=_nodal_connec->getConstPointer();
5520 const int *connI=_nodal_connec_index->getConstPointer();
5521 const double *coords=_coords->getConstPointer();
5522 std::vector<double> addCoo;
5523 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5524 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5525 newConnI->alloc(nbCells+1,1);
5526 int *newConnIPtr=newConnI->getPointer();
5529 INTERP_KERNEL::Node *tmp2[3];
5530 std::set<INTERP_KERNEL::NormalizedCellType> types;
5531 for(int i=0;i<nbCells;i++,newConnIPtr++)
5533 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5534 if(cm.isQuadratic())
5535 {//assert(connI[i+1]-connI[i]-1==3)
5536 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5537 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5538 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5539 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5540 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5543 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5544 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5546 newConnIPtr[1]=(int)newConn.size();
5550 types.insert(INTERP_KERNEL::NORM_SEG2);
5551 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5552 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5553 newConnIPtr[1]=newConnIPtr[0]+3;
5558 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5559 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5560 newConnIPtr[1]=newConnIPtr[0]+3;
5563 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5566 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5568 newConnArr->alloc((int)newConn.size(),1);
5569 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5570 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5571 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5572 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5573 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5574 std::copy(addCoo.begin(),addCoo.end(),work);
5575 DataArrayDouble::SetArrayIn(newCoords,_coords);
5580 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5581 * In addition, returns an array mapping new cells to old ones. <br>
5582 * This method typically increases the number of cells in \a this mesh
5583 * but the number of nodes remains \b unchanged.
5584 * That's why the 3D splitting policies
5585 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5586 * \param [in] policy - specifies a pattern used for splitting.
5587 * The semantic of \a policy is:
5588 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5589 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5590 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5591 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5594 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5595 * an id of old cell producing it. The caller is to delete this array using
5596 * decrRef() as it is no more needed.
5598 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5599 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5600 * and \a this->getMeshDimension() != 3.
5601 * \throw If \a policy is not one of the four discussed above.
5602 * \throw If the nodal connectivity of cells is not defined.
5603 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5605 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5610 return simplexizePol0();
5612 return simplexizePol1();
5613 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5614 return simplexizePlanarFace5();
5615 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5616 return simplexizePlanarFace6();
5618 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)");
5623 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5624 * - 1D: INTERP_KERNEL::NORM_SEG2
5625 * - 2D: INTERP_KERNEL::NORM_TRI3
5626 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5628 * This method is useful for users that need to use P1 field services as
5629 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5630 * All these methods need mesh support containing only simplex cells.
5631 * \return bool - \c true if there are only simplex cells in \a this mesh.
5632 * \throw If the coordinates array is not set.
5633 * \throw If the nodal connectivity of cells is not defined.
5634 * \throw If \a this->getMeshDimension() < 1.
5636 bool MEDCouplingUMesh::areOnlySimplexCells() const
5638 checkFullyDefined();
5639 int mdim=getMeshDimension();
5640 if(mdim<1 || mdim>3)
5641 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5642 int nbCells=getNumberOfCells();
5643 const int *conn=_nodal_connec->getConstPointer();
5644 const int *connI=_nodal_connec_index->getConstPointer();
5645 for(int i=0;i<nbCells;i++)
5647 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5655 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5657 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5659 checkConnectivityFullyDefined();
5660 if(getMeshDimension()!=2)
5661 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5662 int nbOfCells=getNumberOfCells();
5663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5664 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5665 ret->alloc(nbOfCells+nbOfCutCells,1);
5666 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5667 int *retPt=ret->getPointer();
5668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5670 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5671 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5672 int *pt=newConn->getPointer();
5673 int *ptI=newConnI->getPointer();
5675 const int *oldc=_nodal_connec->getConstPointer();
5676 const int *ci=_nodal_connec_index->getConstPointer();
5677 for(int i=0;i<nbOfCells;i++,ci++)
5679 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5681 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5682 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5683 pt=std::copy(tmp,tmp+8,pt);
5692 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5693 ptI[1]=ptI[0]+ci[1]-ci[0];
5698 _nodal_connec->decrRef();
5699 _nodal_connec=newConn.retn();
5700 _nodal_connec_index->decrRef();
5701 _nodal_connec_index=newConnI.retn();
5708 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5710 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5712 checkConnectivityFullyDefined();
5713 if(getMeshDimension()!=2)
5714 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5715 int nbOfCells=getNumberOfCells();
5716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5717 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5718 ret->alloc(nbOfCells+nbOfCutCells,1);
5719 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5720 int *retPt=ret->getPointer();
5721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5722 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5723 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5724 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5725 int *pt=newConn->getPointer();
5726 int *ptI=newConnI->getPointer();
5728 const int *oldc=_nodal_connec->getConstPointer();
5729 const int *ci=_nodal_connec_index->getConstPointer();
5730 for(int i=0;i<nbOfCells;i++,ci++)
5732 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5734 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5735 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5736 pt=std::copy(tmp,tmp+8,pt);
5745 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5746 ptI[1]=ptI[0]+ci[1]-ci[0];
5751 _nodal_connec->decrRef();
5752 _nodal_connec=newConn.retn();
5753 _nodal_connec_index->decrRef();
5754 _nodal_connec_index=newConnI.retn();
5761 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5763 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5765 checkConnectivityFullyDefined();
5766 if(getMeshDimension()!=3)
5767 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5768 int nbOfCells=getNumberOfCells();
5769 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5770 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5771 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5772 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5773 int *retPt=ret->getPointer();
5774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5776 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5777 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5778 int *pt=newConn->getPointer();
5779 int *ptI=newConnI->getPointer();
5781 const int *oldc=_nodal_connec->getConstPointer();
5782 const int *ci=_nodal_connec_index->getConstPointer();
5783 for(int i=0;i<nbOfCells;i++,ci++)
5785 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5787 for(int j=0;j<5;j++,pt+=5,ptI++)
5789 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5790 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];
5797 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5798 ptI[1]=ptI[0]+ci[1]-ci[0];
5803 _nodal_connec->decrRef();
5804 _nodal_connec=newConn.retn();
5805 _nodal_connec_index->decrRef();
5806 _nodal_connec_index=newConnI.retn();
5813 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5815 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5817 checkConnectivityFullyDefined();
5818 if(getMeshDimension()!=3)
5819 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5820 int nbOfCells=getNumberOfCells();
5821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5822 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5823 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5824 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5825 int *retPt=ret->getPointer();
5826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5827 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5828 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5829 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5830 int *pt=newConn->getPointer();
5831 int *ptI=newConnI->getPointer();
5833 const int *oldc=_nodal_connec->getConstPointer();
5834 const int *ci=_nodal_connec_index->getConstPointer();
5835 for(int i=0;i<nbOfCells;i++,ci++)
5837 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5839 for(int j=0;j<6;j++,pt+=5,ptI++)
5841 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5842 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];
5849 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5850 ptI[1]=ptI[0]+ci[1]-ci[0];
5855 _nodal_connec->decrRef();
5856 _nodal_connec=newConn.retn();
5857 _nodal_connec_index->decrRef();
5858 _nodal_connec_index=newConnI.retn();
5865 * 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.
5866 * This method completly ignore coordinates.
5867 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5868 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5869 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5870 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5872 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5874 checkFullyDefined();
5875 if(getMeshDimension()!=2)
5876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5877 int nbOfCells=getNumberOfCells();
5878 int *connI=_nodal_connec_index->getPointer();
5880 for(int i=0;i<nbOfCells;i++,connI++)
5882 int offset=descIndex[i];
5883 int nbOfEdges=descIndex[i+1]-offset;
5885 bool ddirect=desc[offset+nbOfEdges-1]>0;
5886 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5887 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5888 for(int j=0;j<nbOfEdges;j++)
5890 bool direct=desc[offset+j]>0;
5891 int edgeId=std::abs(desc[offset+j])-1;
5892 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5894 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5895 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5896 int ref2=direct?id1:id2;
5899 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5900 newConnLgth+=nbOfSubNodes-1;
5905 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5906 throw INTERP_KERNEL::Exception(oss.str().c_str());
5911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5914 newConnLgth++;//+1 is for cell type
5915 connI[1]=newConnLgth;
5918 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5919 newConn->alloc(newConnLgth,1);
5920 int *work=newConn->getPointer();
5921 for(int i=0;i<nbOfCells;i++)
5923 *work++=INTERP_KERNEL::NORM_POLYGON;
5924 int offset=descIndex[i];
5925 int nbOfEdges=descIndex[i+1]-offset;
5926 for(int j=0;j<nbOfEdges;j++)
5928 bool direct=desc[offset+j]>0;
5929 int edgeId=std::abs(desc[offset+j])-1;
5931 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5934 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5935 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5936 work=std::copy(it,it+nbOfSubNodes-1,work);
5940 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5943 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5947 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5948 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5949 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5950 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5951 * so it can be useful to call mergeNodes() before calling this method.
5952 * \throw If \a this->getMeshDimension() <= 1.
5953 * \throw If the coordinates array is not set.
5954 * \throw If the nodal connectivity of cells is not defined.
5956 void MEDCouplingUMesh::convertDegeneratedCells()
5958 checkFullyDefined();
5959 if(getMeshDimension()<=1)
5960 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5961 int nbOfCells=getNumberOfCells();
5964 int initMeshLgth=getMeshLength();
5965 int *conn=_nodal_connec->getPointer();
5966 int *index=_nodal_connec_index->getPointer();
5970 for(int i=0;i<nbOfCells;i++)
5972 lgthOfCurCell=index[i+1]-posOfCurCell;
5973 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5975 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5976 conn+newPos+1,newLgth);
5977 conn[newPos]=newType;
5979 posOfCurCell=index[i+1];
5982 if(newPos!=initMeshLgth)
5983 _nodal_connec->reAlloc(newPos);
5988 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5989 * A cell is considered to be oriented correctly if an angle between its
5990 * normal vector and a given vector is less than \c PI / \c 2.
5991 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5993 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5995 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5996 * is not cleared before filling in.
5997 * \throw If \a this->getMeshDimension() != 2.
5998 * \throw If \a this->getSpaceDimension() != 3.
6000 * \if ENABLE_EXAMPLES
6001 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6002 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6005 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6007 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6008 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6009 int nbOfCells=getNumberOfCells();
6010 const int *conn=_nodal_connec->getConstPointer();
6011 const int *connI=_nodal_connec_index->getConstPointer();
6012 const double *coordsPtr=_coords->getConstPointer();
6013 for(int i=0;i<nbOfCells;i++)
6015 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6016 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6018 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6019 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6026 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6027 * considered to be oriented correctly if an angle between its normal vector and a
6028 * given vector is less than \c PI / \c 2.
6029 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6031 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6033 * \throw If \a this->getMeshDimension() != 2.
6034 * \throw If \a this->getSpaceDimension() != 3.
6036 * \if ENABLE_EXAMPLES
6037 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6038 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6041 * \sa changeOrientationOfCells
6043 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6045 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6046 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6047 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6048 const int *connI(_nodal_connec_index->getConstPointer());
6049 const double *coordsPtr(_coords->getConstPointer());
6050 bool isModified(false);
6051 for(int i=0;i<nbOfCells;i++)
6053 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6054 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6056 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6057 bool isQuadratic(cm.isQuadratic());
6058 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6061 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6066 _nodal_connec->declareAsNew();
6071 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6073 * \sa orientCorrectly2DCells
6075 void MEDCouplingUMesh::changeOrientationOfCells()
6077 int mdim(getMeshDimension());
6078 if(mdim!=2 && mdim!=1)
6079 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6080 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6081 const int *connI(_nodal_connec_index->getConstPointer());
6084 for(int i=0;i<nbOfCells;i++)
6086 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6087 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6088 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6093 for(int i=0;i<nbOfCells;i++)
6095 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6096 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6097 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6103 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6104 * oriented facets. The normal vector of the facet should point out of the cell.
6105 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6106 * is not cleared before filling in.
6107 * \throw If \a this->getMeshDimension() != 3.
6108 * \throw If \a this->getSpaceDimension() != 3.
6109 * \throw If the coordinates array is not set.
6110 * \throw If the nodal connectivity of cells is not defined.
6112 * \if ENABLE_EXAMPLES
6113 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6114 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6117 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6119 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6120 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6121 int nbOfCells=getNumberOfCells();
6122 const int *conn=_nodal_connec->getConstPointer();
6123 const int *connI=_nodal_connec_index->getConstPointer();
6124 const double *coordsPtr=_coords->getConstPointer();
6125 for(int i=0;i<nbOfCells;i++)
6127 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6128 if(type==INTERP_KERNEL::NORM_POLYHED)
6130 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6137 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6139 * \throw If \a this->getMeshDimension() != 3.
6140 * \throw If \a this->getSpaceDimension() != 3.
6141 * \throw If the coordinates array is not set.
6142 * \throw If the nodal connectivity of cells is not defined.
6143 * \throw If the reparation fails.
6145 * \if ENABLE_EXAMPLES
6146 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6147 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6149 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6151 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6153 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6154 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6155 int nbOfCells=getNumberOfCells();
6156 int *conn=_nodal_connec->getPointer();
6157 const int *connI=_nodal_connec_index->getConstPointer();
6158 const double *coordsPtr=_coords->getConstPointer();
6159 for(int i=0;i<nbOfCells;i++)
6161 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6162 if(type==INTERP_KERNEL::NORM_POLYHED)
6166 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6167 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6169 catch(INTERP_KERNEL::Exception& e)
6171 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6172 throw INTERP_KERNEL::Exception(oss.str().c_str());
6180 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6181 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6182 * according to which the first facet of the cell should be oriented to have the normal vector
6183 * pointing out of cell.
6184 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6185 * cells. The caller is to delete this array using decrRef() as it is no more
6187 * \throw If \a this->getMeshDimension() != 3.
6188 * \throw If \a this->getSpaceDimension() != 3.
6189 * \throw If the coordinates array is not set.
6190 * \throw If the nodal connectivity of cells is not defined.
6192 * \if ENABLE_EXAMPLES
6193 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6194 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6196 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6198 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6200 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6201 if(getMeshDimension()!=3)
6202 throw INTERP_KERNEL::Exception(msg);
6203 int spaceDim=getSpaceDimension();
6205 throw INTERP_KERNEL::Exception(msg);
6207 int nbOfCells=getNumberOfCells();
6208 int *conn=_nodal_connec->getPointer();
6209 const int *connI=_nodal_connec_index->getConstPointer();
6210 const double *coo=getCoords()->getConstPointer();
6211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6212 for(int i=0;i<nbOfCells;i++)
6214 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6215 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6217 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6219 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6220 cells->pushBackSilent(i);
6224 return cells.retn();
6228 * This method is a faster method to correct orientation of all 3D cells in \a this.
6229 * 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.
6230 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6232 * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6233 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6235 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6237 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6238 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6239 int nbOfCells=getNumberOfCells();
6240 int *conn=_nodal_connec->getPointer();
6241 const int *connI=_nodal_connec_index->getConstPointer();
6242 const double *coordsPtr=_coords->getConstPointer();
6243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6244 for(int i=0;i<nbOfCells;i++)
6246 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6249 case INTERP_KERNEL::NORM_TETRA4:
6251 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6253 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6254 ret->pushBackSilent(i);
6258 case INTERP_KERNEL::NORM_PYRA5:
6260 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6262 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6263 ret->pushBackSilent(i);
6267 case INTERP_KERNEL::NORM_PENTA6:
6268 case INTERP_KERNEL::NORM_HEXA8:
6269 case INTERP_KERNEL::NORM_HEXGP12:
6271 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6273 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6274 ret->pushBackSilent(i);
6278 case INTERP_KERNEL::NORM_POLYHED:
6280 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6282 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6283 ret->pushBackSilent(i);
6288 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 !");
6296 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6297 * If it is not the case an exception will be thrown.
6298 * This method is fast because the first cell of \a this is used to compute the plane.
6299 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6300 * \param pos output of size at least 3 used to store a point owned of searched plane.
6302 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6304 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6305 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6306 const int *conn=_nodal_connec->getConstPointer();
6307 const int *connI=_nodal_connec_index->getConstPointer();
6308 const double *coordsPtr=_coords->getConstPointer();
6309 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6310 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6314 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6315 * cells. Currently cells of the following types are treated:
6316 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6317 * For a cell of other type an exception is thrown.
6318 * Space dimension of a 2D mesh can be either 2 or 3.
6319 * The Edge Ratio of a cell \f$t\f$ is:
6320 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6321 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6322 * the smallest edge lengths of \f$t\f$.
6323 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6324 * cells and one time, lying on \a this mesh. The caller is to delete this
6325 * field using decrRef() as it is no more needed.
6326 * \throw If the coordinates array is not set.
6327 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6328 * \throw If the connectivity data array has more than one component.
6329 * \throw If the connectivity data array has a named component.
6330 * \throw If the connectivity index data array has more than one component.
6331 * \throw If the connectivity index data array has a named component.
6332 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6333 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6334 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6336 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6339 int spaceDim=getSpaceDimension();
6340 int meshDim=getMeshDimension();
6341 if(spaceDim!=2 && spaceDim!=3)
6342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6343 if(meshDim!=2 && meshDim!=3)
6344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6347 int nbOfCells=getNumberOfCells();
6348 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6349 arr->alloc(nbOfCells,1);
6350 double *pt=arr->getPointer();
6351 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6352 const int *conn=_nodal_connec->getConstPointer();
6353 const int *connI=_nodal_connec_index->getConstPointer();
6354 const double *coo=_coords->getConstPointer();
6356 for(int i=0;i<nbOfCells;i++,pt++)
6358 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6361 case INTERP_KERNEL::NORM_TRI3:
6363 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6364 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6367 case INTERP_KERNEL::NORM_QUAD4:
6369 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6370 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6373 case INTERP_KERNEL::NORM_TETRA4:
6375 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6376 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6380 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6382 conn+=connI[i+1]-connI[i];
6384 ret->setName("EdgeRatio");
6385 ret->synchronizeTimeWithSupport();
6390 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6391 * cells. Currently cells of the following types are treated:
6392 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6393 * For a cell of other type an exception is thrown.
6394 * Space dimension of a 2D mesh can be either 2 or 3.
6395 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6396 * cells and one time, lying on \a this mesh. The caller is to delete this
6397 * field using decrRef() as it is no more needed.
6398 * \throw If the coordinates array is not set.
6399 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6400 * \throw If the connectivity data array has more than one component.
6401 * \throw If the connectivity data array has a named component.
6402 * \throw If the connectivity index data array has more than one component.
6403 * \throw If the connectivity index data array has a named component.
6404 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6405 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6406 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6408 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6411 int spaceDim=getSpaceDimension();
6412 int meshDim=getMeshDimension();
6413 if(spaceDim!=2 && spaceDim!=3)
6414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6415 if(meshDim!=2 && meshDim!=3)
6416 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6417 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6419 int nbOfCells=getNumberOfCells();
6420 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6421 arr->alloc(nbOfCells,1);
6422 double *pt=arr->getPointer();
6423 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6424 const int *conn=_nodal_connec->getConstPointer();
6425 const int *connI=_nodal_connec_index->getConstPointer();
6426 const double *coo=_coords->getConstPointer();
6428 for(int i=0;i<nbOfCells;i++,pt++)
6430 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6433 case INTERP_KERNEL::NORM_TRI3:
6435 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6436 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6439 case INTERP_KERNEL::NORM_QUAD4:
6441 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6442 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6445 case INTERP_KERNEL::NORM_TETRA4:
6447 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6448 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6454 conn+=connI[i+1]-connI[i];
6456 ret->setName("AspectRatio");
6457 ret->synchronizeTimeWithSupport();
6462 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6463 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6464 * treated: INTERP_KERNEL::NORM_QUAD4.
6465 * For a cell of other type an exception is thrown.
6466 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6467 * cells and one time, lying on \a this mesh. The caller is to delete this
6468 * field using decrRef() as it is no more needed.
6469 * \throw If the coordinates array is not set.
6470 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6471 * \throw If the connectivity data array has more than one component.
6472 * \throw If the connectivity data array has a named component.
6473 * \throw If the connectivity index data array has more than one component.
6474 * \throw If the connectivity index data array has a named component.
6475 * \throw If \a this->getMeshDimension() != 2.
6476 * \throw If \a this->getSpaceDimension() != 3.
6477 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6479 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6482 int spaceDim=getSpaceDimension();
6483 int meshDim=getMeshDimension();
6485 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6487 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6488 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6490 int nbOfCells=getNumberOfCells();
6491 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6492 arr->alloc(nbOfCells,1);
6493 double *pt=arr->getPointer();
6494 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6495 const int *conn=_nodal_connec->getConstPointer();
6496 const int *connI=_nodal_connec_index->getConstPointer();
6497 const double *coo=_coords->getConstPointer();
6499 for(int i=0;i<nbOfCells;i++,pt++)
6501 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6504 case INTERP_KERNEL::NORM_QUAD4:
6506 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6507 *pt=INTERP_KERNEL::quadWarp(tmp);
6511 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6513 conn+=connI[i+1]-connI[i];
6515 ret->setName("Warp");
6516 ret->synchronizeTimeWithSupport();
6522 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6523 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6524 * treated: INTERP_KERNEL::NORM_QUAD4.
6525 * For a cell of other type an exception is thrown.
6526 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6527 * cells and one time, lying on \a this mesh. The caller is to delete this
6528 * field using decrRef() as it is no more needed.
6529 * \throw If the coordinates array is not set.
6530 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6531 * \throw If the connectivity data array has more than one component.
6532 * \throw If the connectivity data array has a named component.
6533 * \throw If the connectivity index data array has more than one component.
6534 * \throw If the connectivity index data array has a named component.
6535 * \throw If \a this->getMeshDimension() != 2.
6536 * \throw If \a this->getSpaceDimension() != 3.
6537 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6539 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6542 int spaceDim=getSpaceDimension();
6543 int meshDim=getMeshDimension();
6545 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6547 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6548 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6550 int nbOfCells=getNumberOfCells();
6551 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6552 arr->alloc(nbOfCells,1);
6553 double *pt=arr->getPointer();
6554 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6555 const int *conn=_nodal_connec->getConstPointer();
6556 const int *connI=_nodal_connec_index->getConstPointer();
6557 const double *coo=_coords->getConstPointer();
6559 for(int i=0;i<nbOfCells;i++,pt++)
6561 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6564 case INTERP_KERNEL::NORM_QUAD4:
6566 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6567 *pt=INTERP_KERNEL::quadSkew(tmp);
6571 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6573 conn+=connI[i+1]-connI[i];
6575 ret->setName("Skew");
6576 ret->synchronizeTimeWithSupport();
6581 * 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.
6583 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6585 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6587 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6590 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6592 std::set<INTERP_KERNEL::NormalizedCellType> types;
6593 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6594 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6595 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6596 arr->alloc(nbCells,1);
6597 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6599 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6601 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6604 ret->setName("Diameter");
6609 * This method aggregate the bbox of each cell and put it into bbox parameter.
6611 * \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)
6612 * For all other cases this input parameter is ignored.
6613 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6615 * \throw If \a this is not fully set (coordinates and connectivity).
6616 * \throw If a cell in \a this has no valid nodeId.
6617 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6619 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6621 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6622 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.
6623 return getBoundingBoxForBBTreeFast();
6624 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6626 bool presenceOfQuadratic(false);
6627 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6629 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6630 if(cm.isQuadratic())
6631 presenceOfQuadratic=true;
6633 if(!presenceOfQuadratic)
6634 return getBoundingBoxForBBTreeFast();
6635 if(mDim==2 && sDim==2)
6636 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6638 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6640 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) !");
6644 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6645 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6647 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6649 * \throw If \a this is not fully set (coordinates and connectivity).
6650 * \throw If a cell in \a this has no valid nodeId.
6652 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6654 checkFullyDefined();
6655 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6656 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6657 double *bbox(ret->getPointer());
6658 for(int i=0;i<nbOfCells*spaceDim;i++)
6660 bbox[2*i]=std::numeric_limits<double>::max();
6661 bbox[2*i+1]=-std::numeric_limits<double>::max();
6663 const double *coordsPtr(_coords->getConstPointer());
6664 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6665 for(int i=0;i<nbOfCells;i++)
6667 int offset=connI[i]+1;
6668 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6669 for(int j=0;j<nbOfNodesForCell;j++)
6671 int nodeId=conn[offset+j];
6672 if(nodeId>=0 && nodeId<nbOfNodes)
6674 for(int k=0;k<spaceDim;k++)
6676 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6677 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6684 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6685 throw INTERP_KERNEL::Exception(oss.str().c_str());
6692 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6693 * useful for 2D meshes having quadratic cells
6694 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6695 * the two extremities of the arc of circle).
6697 * \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)
6698 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6699 * \throw If \a this is not fully defined.
6700 * \throw If \a this is not a mesh with meshDimension equal to 2.
6701 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6702 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6704 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6706 checkFullyDefined();
6707 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6708 if(spaceDim!=2 || mDim!=2)
6709 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!");
6710 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6711 double *bbox(ret->getPointer());
6712 const double *coords(_coords->getConstPointer());
6713 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6714 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6716 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6717 int sz(connI[1]-connI[0]-1);
6718 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6719 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6720 INTERP_KERNEL::QuadraticPolygon *pol(0);
6721 for(int j=0;j<sz;j++)
6723 int nodeId(conn[*connI+1+j]);
6724 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6726 if(!cm.isQuadratic())
6727 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6729 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6730 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6731 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6737 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6738 * useful for 2D meshes having quadratic cells
6739 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6740 * the two extremities of the arc of circle).
6742 * \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)
6743 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6744 * \throw If \a this is not fully defined.
6745 * \throw If \a this is not a mesh with meshDimension equal to 1.
6746 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6747 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6749 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6751 checkFullyDefined();
6752 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6753 if(spaceDim!=2 || mDim!=1)
6754 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!");
6755 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6756 double *bbox(ret->getPointer());
6757 const double *coords(_coords->getConstPointer());
6758 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6759 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6761 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6762 int sz(connI[1]-connI[0]-1);
6763 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6764 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6765 INTERP_KERNEL::Edge *edge(0);
6766 for(int j=0;j<sz;j++)
6768 int nodeId(conn[*connI+1+j]);
6769 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6771 if(!cm.isQuadratic())
6772 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6774 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6775 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6776 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6783 namespace ParaMEDMEMImpl
6788 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6789 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6798 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6799 bool operator() (const int& pos) { return _conn[pos]==_val; }
6809 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6810 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6811 * \a this is composed in cell types.
6812 * The returned array is of size 3*n where n is the number of different types present in \a this.
6813 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6814 * This parameter is kept only for compatibility with other methode listed above.
6816 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6818 checkConnectivityFullyDefined();
6819 const int *conn=_nodal_connec->getConstPointer();
6820 const int *connI=_nodal_connec_index->getConstPointer();
6821 const int *work=connI;
6822 int nbOfCells=getNumberOfCells();
6823 std::size_t n=getAllGeoTypes().size();
6824 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6825 std::set<INTERP_KERNEL::NormalizedCellType> types;
6826 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6828 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6829 if(types.find(typ)!=types.end())
6831 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6832 oss << " is not contiguous !";
6833 throw INTERP_KERNEL::Exception(oss.str().c_str());
6837 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6838 ret[3*i+1]=(int)std::distance(work,work2);
6845 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6846 * only for types cell, type node is not managed.
6847 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6848 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6849 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6850 * If 2 or more same geometric type is in \a code and exception is thrown too.
6852 * This method firstly checks
6853 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6854 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6855 * an exception is thrown too.
6857 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6858 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6859 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6861 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6865 std::size_t sz=code.size();
6868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6869 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6871 bool isNoPflUsed=true;
6872 for(std::size_t i=0;i<n;i++)
6873 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6875 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6877 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6879 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6882 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6885 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6886 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6887 if(types.size()==_types.size())
6890 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6892 int *retPtr=ret->getPointer();
6893 const int *connI=_nodal_connec_index->getConstPointer();
6894 const int *conn=_nodal_connec->getConstPointer();
6895 int nbOfCells=getNumberOfCells();
6898 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6900 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6901 int offset=(int)std::distance(connI,i);
6902 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6903 int nbOfCellsOfCurType=(int)std::distance(i,j);
6904 if(code[3*kk+2]==-1)
6905 for(int k=0;k<nbOfCellsOfCurType;k++)
6909 int idInIdsPerType=code[3*kk+2];
6910 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6912 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6915 zePfl->checkAllocated();
6916 if(zePfl->getNumberOfComponents()==1)
6918 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6920 if(*k>=0 && *k<nbOfCellsOfCurType)
6921 *retPtr=(*k)+offset;
6924 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6925 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6926 throw INTERP_KERNEL::Exception(oss.str().c_str());
6931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6934 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6938 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6939 oss << " should be in [0," << idsPerType.size() << ") !";
6940 throw INTERP_KERNEL::Exception(oss.str().c_str());
6949 * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6950 * 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.
6951 * 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.
6952 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6954 * \param [in] profile
6955 * \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.
6956 * \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,
6957 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6958 * \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.
6959 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6960 * \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
6962 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6966 if(profile->getNumberOfComponents()!=1)
6967 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6968 checkConnectivityFullyDefined();
6969 const int *conn=_nodal_connec->getConstPointer();
6970 const int *connI=_nodal_connec_index->getConstPointer();
6971 int nbOfCells=getNumberOfCells();
6972 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6973 std::vector<int> typeRangeVals(1);
6974 for(const int *i=connI;i!=connI+nbOfCells;)
6976 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6977 if(std::find(types.begin(),types.end(),curType)!=types.end())
6979 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6981 types.push_back(curType);
6982 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6983 typeRangeVals.push_back((int)std::distance(connI,i));
6986 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6987 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6990 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6992 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6993 code.resize(3*nbOfCastsFinal);
6994 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6995 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6996 for(int i=0;i<nbOfCastsFinal;i++)
6998 int castId=castsPresent->getIJ(i,0);
6999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7000 idsInPflPerType2.push_back(tmp3);
7001 code[3*i]=(int)types[castId];
7002 code[3*i+1]=tmp3->getNumberOfTuples();
7003 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7004 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
7006 tmp4->copyStringInfoFrom(*profile);
7007 idsPerType2.push_back(tmp4);
7008 code[3*i+2]=(int)idsPerType2.size()-1;
7015 std::size_t sz2=idsInPflPerType2.size();
7016 idsInPflPerType.resize(sz2);
7017 for(std::size_t i=0;i<sz2;i++)
7019 DataArrayInt *locDa=idsInPflPerType2[i];
7021 idsInPflPerType[i]=locDa;
7023 std::size_t sz=idsPerType2.size();
7024 idsPerType.resize(sz);
7025 for(std::size_t i=0;i<sz;i++)
7027 DataArrayInt *locDa=idsPerType2[i];
7029 idsPerType[i]=locDa;
7034 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7035 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7036 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7037 * 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.
7039 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7041 checkFullyDefined();
7042 nM1LevMesh->checkFullyDefined();
7043 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7044 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7045 if(_coords!=nM1LevMesh->getCoords())
7046 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7049 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7051 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7052 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7053 tmp->setConnectivity(tmp0,tmp1);
7054 tmp->renumberCells(ret0->getConstPointer(),false);
7055 revDesc=tmp->getNodalConnectivity();
7056 revDescIndx=tmp->getNodalConnectivityIndex();
7057 DataArrayInt *ret=0;
7058 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7061 ret->getMaxValue(tmp2);
7063 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7064 throw INTERP_KERNEL::Exception(oss.str().c_str());
7069 revDescIndx->incrRef();
7072 meshnM1Old2New=ret0;
7077 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7078 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7079 * in "Old to New" mode.
7080 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7081 * this array using decrRef() as it is no more needed.
7082 * \throw If the nodal connectivity of cells is not defined.
7084 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7086 checkConnectivityFullyDefined();
7087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7088 renumberCells(ret->getConstPointer(),false);
7093 * This methods checks that cells are sorted by their types.
7094 * This method makes asumption (no check) that connectivity is correctly set before calling.
7096 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7098 checkFullyDefined();
7099 const int *conn=_nodal_connec->getConstPointer();
7100 const int *connI=_nodal_connec_index->getConstPointer();
7101 int nbOfCells=getNumberOfCells();
7102 std::set<INTERP_KERNEL::NormalizedCellType> types;
7103 for(const int *i=connI;i!=connI+nbOfCells;)
7105 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7106 if(types.find(curType)!=types.end())
7108 types.insert(curType);
7109 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7115 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7116 * The geometric type order is specified by MED file.
7118 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7120 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7122 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7126 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7127 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7128 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7129 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7131 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7133 checkFullyDefined();
7134 const int *conn=_nodal_connec->getConstPointer();
7135 const int *connI=_nodal_connec_index->getConstPointer();
7136 int nbOfCells=getNumberOfCells();
7140 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7141 for(const int *i=connI;i!=connI+nbOfCells;)
7143 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7144 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7145 if(isTypeExists!=orderEnd)
7147 int pos=(int)std::distance(orderBg,isTypeExists);
7151 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7155 if(sg.find(curType)==sg.end())
7157 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7168 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7169 * 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
7170 * 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'.
7172 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7174 checkConnectivityFullyDefined();
7175 int nbOfCells=getNumberOfCells();
7176 const int *conn=_nodal_connec->getConstPointer();
7177 const int *connI=_nodal_connec_index->getConstPointer();
7178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7180 tmpa->alloc(nbOfCells,1);
7181 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7182 tmpb->fillWithZero();
7183 int *tmp=tmpa->getPointer();
7184 int *tmp2=tmpb->getPointer();
7185 for(const int *i=connI;i!=connI+nbOfCells;i++)
7187 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7190 int pos=(int)std::distance(orderBg,where);
7192 tmp[std::distance(connI,i)]=pos;
7196 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7197 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7198 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7199 throw INTERP_KERNEL::Exception(oss.str().c_str());
7202 nbPerType=tmpb.retn();
7207 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7209 * \return a new object containing the old to new correspondance.
7211 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7213 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7215 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7219 * 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.
7220 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7221 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7222 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7224 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7226 DataArrayInt *nbPerType=0;
7227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7228 nbPerType->decrRef();
7229 return tmpa->buildPermArrPerLevel();
7233 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7234 * The number of cells remains unchanged after the call of this method.
7235 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7236 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7238 * \return the array giving the correspondance old to new.
7240 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7242 checkFullyDefined();
7244 const int *conn=_nodal_connec->getConstPointer();
7245 const int *connI=_nodal_connec_index->getConstPointer();
7246 int nbOfCells=getNumberOfCells();
7247 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7248 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7249 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7251 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7252 types.push_back(curType);
7253 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7255 DataArrayInt *ret=DataArrayInt::New();
7256 ret->alloc(nbOfCells,1);
7257 int *retPtr=ret->getPointer();
7258 std::fill(retPtr,retPtr+nbOfCells,-1);
7260 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7262 for(const int *i=connI;i!=connI+nbOfCells;i++)
7263 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7264 retPtr[std::distance(connI,i)]=newCellId++;
7266 renumberCells(retPtr,false);
7271 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7272 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7273 * This method makes asumption that connectivity is correctly set before calling.
7275 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7277 checkConnectivityFullyDefined();
7278 const int *conn=_nodal_connec->getConstPointer();
7279 const int *connI=_nodal_connec_index->getConstPointer();
7280 int nbOfCells=getNumberOfCells();
7281 std::vector<MEDCouplingUMesh *> ret;
7282 for(const int *i=connI;i!=connI+nbOfCells;)
7284 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7285 int beginCellId=(int)std::distance(connI,i);
7286 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7287 int endCellId=(int)std::distance(connI,i);
7288 int sz=endCellId-beginCellId;
7289 int *cells=new int[sz];
7290 for(int j=0;j<sz;j++)
7291 cells[j]=beginCellId+j;
7292 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7300 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7301 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7302 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7304 * \return a newly allocated instance, that the caller must manage.
7305 * \throw If \a this contains more than one geometric type.
7306 * \throw If the nodal connectivity of \a this is not fully defined.
7307 * \throw If the internal data is not coherent.
7309 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7311 checkConnectivityFullyDefined();
7312 if(_types.size()!=1)
7313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7314 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7315 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7316 ret->setCoords(getCoords());
7317 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7321 retC->setNodalConnectivity(c);
7325 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7327 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7328 DataArrayInt *c=0,*ci=0;
7329 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7331 retD->setNodalConnectivity(cs,cis);
7336 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7338 checkConnectivityFullyDefined();
7339 if(_types.size()!=1)
7340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7341 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7342 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7345 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7346 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7347 throw INTERP_KERNEL::Exception(oss.str().c_str());
7349 int nbCells=getNumberOfCells();
7351 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7353 int *outPtr=connOut->getPointer();
7354 const int *conn=_nodal_connec->begin();
7355 const int *connI=_nodal_connec_index->begin();
7357 for(int i=0;i<nbCells;i++,connI++)
7359 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7360 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7363 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 << ") !";
7364 throw INTERP_KERNEL::Exception(oss.str().c_str());
7367 return connOut.retn();
7371 * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7372 * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7376 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7378 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7379 checkConnectivityFullyDefined();
7380 if(_types.size()!=1)
7381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7382 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7384 throw INTERP_KERNEL::Exception(msg0);
7385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7386 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7387 int *cp(c->getPointer()),*cip(ci->getPointer());
7388 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7390 for(int i=0;i<nbCells;i++,cip++,incip++)
7392 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7393 int delta(stop-strt);
7396 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7397 cp=std::copy(incp+strt,incp+stop,cp);
7399 throw INTERP_KERNEL::Exception(msg0);
7402 throw INTERP_KERNEL::Exception(msg0);
7403 cip[1]=cip[0]+delta;
7405 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7409 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7410 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7411 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7412 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7413 * are not used here to avoid the build of big permutation array.
7415 * \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
7416 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7417 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7418 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7419 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7420 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7421 * \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
7422 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7424 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7425 DataArrayInt *&szOfCellGrpOfSameType,
7426 DataArrayInt *&idInMsOfCellGrpOfSameType)
7428 std::vector<const MEDCouplingUMesh *> ms2;
7429 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7432 (*it)->checkConnectivityFullyDefined();
7436 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7437 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7438 int meshDim=ms2[0]->getMeshDimension();
7439 std::vector<const MEDCouplingUMesh *> m1ssm;
7440 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7442 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7443 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7445 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7446 ret1->alloc(0,1); ret2->alloc(0,1);
7447 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7449 if(meshDim!=(*it)->getMeshDimension())
7450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7451 if(refCoo!=(*it)->getCoords())
7452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7453 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7454 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7455 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7456 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7458 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7459 m1ssmSingleAuto.push_back(singleCell);
7460 m1ssmSingle.push_back(singleCell);
7461 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7464 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7466 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7467 for(std::size_t i=0;i<m1ssm.size();i++)
7468 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7469 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7470 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7471 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7476 * This method returns a newly created DataArrayInt instance.
7477 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7479 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7481 checkFullyDefined();
7482 const int *conn=_nodal_connec->getConstPointer();
7483 const int *connIndex=_nodal_connec_index->getConstPointer();
7484 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7485 for(const int *w=begin;w!=end;w++)
7486 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7487 ret->pushBackSilent(*w);
7492 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7493 * are in [0:getNumberOfCells())
7495 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7497 checkFullyDefined();
7498 const int *conn=_nodal_connec->getConstPointer();
7499 const int *connI=_nodal_connec_index->getConstPointer();
7500 int nbOfCells=getNumberOfCells();
7501 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7502 int *tmp=new int[nbOfCells];
7503 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7506 for(const int *i=connI;i!=connI+nbOfCells;i++)
7507 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7508 tmp[std::distance(connI,i)]=j++;
7510 DataArrayInt *ret=DataArrayInt::New();
7511 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7512 ret->copyStringInfoFrom(*da);
7513 int *retPtr=ret->getPointer();
7514 const int *daPtr=da->getConstPointer();
7515 int nbOfElems=da->getNbOfElems();
7516 for(int k=0;k<nbOfElems;k++)
7517 retPtr[k]=tmp[daPtr[k]];
7523 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7524 * This method \b works \b for mesh sorted by type.
7525 * cells whose ids is in 'idsPerGeoType' array.
7526 * This method conserves coords and name of mesh.
7528 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7530 std::vector<int> code=getDistributionOfTypes();
7531 std::size_t nOfTypesInThis=code.size()/3;
7532 int sz=0,szOfType=0;
7533 for(std::size_t i=0;i<nOfTypesInThis;i++)
7538 szOfType=code[3*i+1];
7540 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7541 if(*work<0 || *work>=szOfType)
7543 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7544 oss << ". It should be in [0," << szOfType << ") !";
7545 throw INTERP_KERNEL::Exception(oss.str().c_str());
7547 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7548 int *idsPtr=idsTokeep->getPointer();
7550 for(std::size_t i=0;i<nOfTypesInThis;i++)
7553 for(int j=0;j<code[3*i+1];j++)
7556 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7557 offset+=code[3*i+1];
7559 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7560 ret->copyTinyInfoFrom(this);
7565 * This method returns a vector of size 'this->getNumberOfCells()'.
7566 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7568 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7570 int ncell=getNumberOfCells();
7571 std::vector<bool> ret(ncell);
7572 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7573 const int *c=getNodalConnectivity()->getConstPointer();
7574 for(int i=0;i<ncell;i++)
7576 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7577 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7578 ret[i]=cm.isQuadratic();
7584 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7586 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7588 if(other->getType()!=UNSTRUCTURED)
7589 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7590 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7591 return MergeUMeshes(this,otherC);
7595 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7596 * computed by averaging coordinates of cell nodes, so this method is not a right
7597 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7598 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7599 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7600 * components. The caller is to delete this array using decrRef() as it is
7602 * \throw If the coordinates array is not set.
7603 * \throw If the nodal connectivity of cells is not defined.
7604 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7606 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7608 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7609 int spaceDim=getSpaceDimension();
7610 int nbOfCells=getNumberOfCells();
7611 ret->alloc(nbOfCells,spaceDim);
7612 ret->copyStringInfoFrom(*getCoords());
7613 double *ptToFill=ret->getPointer();
7614 const int *nodal=_nodal_connec->getConstPointer();
7615 const int *nodalI=_nodal_connec_index->getConstPointer();
7616 const double *coor=_coords->getConstPointer();
7617 for(int i=0;i<nbOfCells;i++)
7619 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7620 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7627 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7628 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7630 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7631 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7633 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7634 * \throw If \a this is not fully defined (coordinates and connectivity)
7635 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7637 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7639 checkFullyDefined();
7640 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7641 int spaceDim=getSpaceDimension();
7642 int nbOfCells=getNumberOfCells();
7643 int nbOfNodes=getNumberOfNodes();
7644 ret->alloc(nbOfCells,spaceDim);
7645 double *ptToFill=ret->getPointer();
7646 const int *nodal=_nodal_connec->getConstPointer();
7647 const int *nodalI=_nodal_connec_index->getConstPointer();
7648 const double *coor=_coords->getConstPointer();
7649 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7651 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7652 std::fill(ptToFill,ptToFill+spaceDim,0.);
7653 if(type!=INTERP_KERNEL::NORM_POLYHED)
7655 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7657 if(*conn>=0 && *conn<nbOfNodes)
7658 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7661 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7662 throw INTERP_KERNEL::Exception(oss.str().c_str());
7665 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7666 if(nbOfNodesInCell>0)
7667 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7670 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7671 throw INTERP_KERNEL::Exception(oss.str().c_str());
7676 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7678 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7680 if(*it>=0 && *it<nbOfNodes)
7681 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7684 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7685 throw INTERP_KERNEL::Exception(oss.str().c_str());
7689 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7692 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7693 throw INTERP_KERNEL::Exception(oss.str().c_str());
7701 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7702 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7703 * are specified via an array of cell ids.
7704 * \warning Validity of the specified cell ids is not checked!
7705 * Valid range is [ 0, \a this->getNumberOfCells() ).
7706 * \param [in] begin - an array of cell ids of interest.
7707 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7708 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7709 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7710 * caller is to delete this array using decrRef() as it is no more needed.
7711 * \throw If the coordinates array is not set.
7712 * \throw If the nodal connectivity of cells is not defined.
7714 * \if ENABLE_EXAMPLES
7715 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7716 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7719 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7721 DataArrayDouble *ret=DataArrayDouble::New();
7722 int spaceDim=getSpaceDimension();
7723 int nbOfTuple=(int)std::distance(begin,end);
7724 ret->alloc(nbOfTuple,spaceDim);
7725 double *ptToFill=ret->getPointer();
7726 double *tmp=new double[spaceDim];
7727 const int *nodal=_nodal_connec->getConstPointer();
7728 const int *nodalI=_nodal_connec_index->getConstPointer();
7729 const double *coor=_coords->getConstPointer();
7730 for(const int *w=begin;w!=end;w++)
7732 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7733 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7741 * 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".
7742 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7743 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7744 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7745 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7747 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7748 * \throw If spaceDim!=3 or meshDim!=2.
7749 * \throw If connectivity of \a this is invalid.
7750 * \throw If connectivity of a cell in \a this points to an invalid node.
7752 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7754 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7755 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7756 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7758 ret->alloc(nbOfCells,4);
7759 double *retPtr(ret->getPointer());
7760 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7761 const double *coor(_coords->begin());
7762 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7764 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7765 if(nodalI[1]-nodalI[0]>=3)
7767 for(int j=0;j<3;j++)
7769 int nodeId(nodal[nodalI[0]+1+j]);
7770 if(nodeId>=0 && nodeId<nbOfNodes)
7771 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7774 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7775 throw INTERP_KERNEL::Exception(oss.str().c_str());
7781 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7782 throw INTERP_KERNEL::Exception(oss.str().c_str());
7784 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7785 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7791 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7794 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7798 da->checkAllocated();
7799 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7801 int nbOfTuples=da->getNumberOfTuples();
7802 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7804 c->alloc(2*nbOfTuples,1);
7805 cI->alloc(nbOfTuples+1,1);
7806 int *cp=c->getPointer();
7807 int *cip=cI->getPointer();
7809 for(int i=0;i<nbOfTuples;i++)
7811 *cp++=INTERP_KERNEL::NORM_POINT1;
7815 ret->setConnectivity(c,cI,true);
7819 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7820 * Cells and nodes of
7821 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7822 * \param [in] mesh1 - the first mesh.
7823 * \param [in] mesh2 - the second mesh.
7824 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7825 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7826 * is no more needed.
7827 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7828 * \throw If the coordinates array is not set in none of the meshes.
7829 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7830 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7832 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7834 std::vector<const MEDCouplingUMesh *> tmp(2);
7835 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7836 return MergeUMeshes(tmp);
7840 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7841 * Cells and nodes of
7842 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7843 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7844 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7845 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7846 * is no more needed.
7847 * \throw If \a a.size() == 0.
7848 * \throw If \a a[ *i* ] == NULL.
7849 * \throw If the coordinates array is not set in none of the meshes.
7850 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7851 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7853 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7855 std::size_t sz=a.size();
7857 return MergeUMeshesLL(a);
7858 for(std::size_t ii=0;ii<sz;ii++)
7861 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7862 throw INTERP_KERNEL::Exception(oss.str().c_str());
7864 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7865 std::vector< const MEDCouplingUMesh * > aa(sz);
7867 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7869 const MEDCouplingUMesh *cur=a[i];
7870 const DataArrayDouble *coo=cur->getCoords();
7872 spaceDim=coo->getNumberOfComponents();
7875 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7876 for(std::size_t i=0;i<sz;i++)
7878 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7881 return MergeUMeshesLL(aa);
7886 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7889 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7890 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7891 int meshDim=(*it)->getMeshDimension();
7892 int nbOfCells=(*it)->getNumberOfCells();
7893 int meshLgth=(*it++)->getMeshLength();
7894 for(;it!=a.end();it++)
7896 if(meshDim!=(*it)->getMeshDimension())
7897 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7898 nbOfCells+=(*it)->getNumberOfCells();
7899 meshLgth+=(*it)->getMeshLength();
7901 std::vector<const MEDCouplingPointSet *> aps(a.size());
7902 std::copy(a.begin(),a.end(),aps.begin());
7903 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7904 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7905 ret->setCoords(pts);
7906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7907 c->alloc(meshLgth,1);
7908 int *cPtr=c->getPointer();
7909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7910 cI->alloc(nbOfCells+1,1);
7911 int *cIPtr=cI->getPointer();
7915 for(it=a.begin();it!=a.end();it++)
7917 int curNbOfCell=(*it)->getNumberOfCells();
7918 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7919 const int *curC=(*it)->_nodal_connec->getConstPointer();
7920 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7921 for(int j=0;j<curNbOfCell;j++)
7923 const int *src=curC+curCI[j];
7925 for(;src!=curC+curCI[j+1];src++,cPtr++)
7933 offset+=curCI[curNbOfCell];
7934 offset2+=(*it)->getNumberOfNodes();
7937 ret->setConnectivity(c,cI,true);
7944 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7945 * dimension and sharing the node coordinates array.
7946 * All cells of the first mesh precede all cells of the second mesh
7947 * within the result mesh.
7948 * \param [in] mesh1 - the first mesh.
7949 * \param [in] mesh2 - the second mesh.
7950 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7951 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7952 * is no more needed.
7953 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7954 * \throw If the meshes do not share the node coordinates array.
7955 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7956 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7958 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7960 std::vector<const MEDCouplingUMesh *> tmp(2);
7961 tmp[0]=mesh1; tmp[1]=mesh2;
7962 return MergeUMeshesOnSameCoords(tmp);
7966 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7967 * dimension and sharing the node coordinates array.
7968 * All cells of the *i*-th mesh precede all cells of the
7969 * (*i*+1)-th mesh within the result mesh.
7970 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7971 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7972 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7973 * is no more needed.
7974 * \throw If \a a.size() == 0.
7975 * \throw If \a a[ *i* ] == NULL.
7976 * \throw If the meshes do not share the node coordinates array.
7977 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7978 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7980 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7983 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7984 for(std::size_t ii=0;ii<meshes.size();ii++)
7987 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7988 throw INTERP_KERNEL::Exception(oss.str().c_str());
7990 const DataArrayDouble *coords=meshes.front()->getCoords();
7991 int meshDim=meshes.front()->getMeshDimension();
7992 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7994 int meshIndexLgth=0;
7995 for(;iter!=meshes.end();iter++)
7997 if(coords!=(*iter)->getCoords())
7998 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7999 if(meshDim!=(*iter)->getMeshDimension())
8000 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8001 meshLgth+=(*iter)->getMeshLength();
8002 meshIndexLgth+=(*iter)->getNumberOfCells();
8004 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8005 nodal->alloc(meshLgth,1);
8006 int *nodalPtr=nodal->getPointer();
8007 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8008 nodalIndex->alloc(meshIndexLgth+1,1);
8009 int *nodalIndexPtr=nodalIndex->getPointer();
8011 for(iter=meshes.begin();iter!=meshes.end();iter++)
8013 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8014 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8015 int nbOfCells=(*iter)->getNumberOfCells();
8016 int meshLgth2=(*iter)->getMeshLength();
8017 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8018 if(iter!=meshes.begin())
8019 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8021 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8024 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8025 ret->setName("merge");
8026 ret->setMeshDimension(meshDim);
8027 ret->setConnectivity(nodal,nodalIndex,true);
8028 ret->setCoords(coords);
8033 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8034 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8035 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8036 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8037 * New" mode are returned for each input mesh.
8038 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8039 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8040 * valid values [0,1,2], see zipConnectivityTraducer().
8041 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8042 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8043 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8045 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8046 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8047 * is no more needed.
8048 * \throw If \a meshes.size() == 0.
8049 * \throw If \a meshes[ *i* ] == NULL.
8050 * \throw If the meshes do not share the node coordinates array.
8051 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8052 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8053 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8054 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8056 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8058 //All checks are delegated to MergeUMeshesOnSameCoords
8059 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8061 corr.resize(meshes.size());
8062 std::size_t nbOfMeshes=meshes.size();
8064 const int *o2nPtr=o2n->getConstPointer();
8065 for(std::size_t i=0;i<nbOfMeshes;i++)
8067 DataArrayInt *tmp=DataArrayInt::New();
8068 int curNbOfCells=meshes[i]->getNumberOfCells();
8069 tmp->alloc(curNbOfCells,1);
8070 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8071 offset+=curNbOfCells;
8072 tmp->setName(meshes[i]->getName());
8079 * Makes all given meshes share the nodal connectivity array. The common connectivity
8080 * array is created by concatenating the connectivity arrays of all given meshes. All
8081 * the given meshes must be of the same space dimension but dimension of cells **can
8082 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8083 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8084 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8085 * \param [in,out] meshes - a vector of meshes to update.
8086 * \throw If any of \a meshes is NULL.
8087 * \throw If the coordinates array is not set in any of \a meshes.
8088 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8089 * \throw If \a meshes are of different space dimension.
8091 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8093 std::size_t sz=meshes.size();
8096 std::vector< const DataArrayDouble * > coords(meshes.size());
8097 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8098 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8102 (*it)->checkConnectivityFullyDefined();
8103 const DataArrayDouble *coo=(*it)->getCoords();
8108 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8109 oss << " has no coordinate array defined !";
8110 throw INTERP_KERNEL::Exception(oss.str().c_str());
8115 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8116 oss << " is null !";
8117 throw INTERP_KERNEL::Exception(oss.str().c_str());
8120 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8121 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8122 int offset=(*it)->getNumberOfNodes();
8123 (*it++)->setCoords(res);
8124 for(;it!=meshes.end();it++)
8126 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8127 (*it)->setCoords(res);
8128 (*it)->shiftNodeNumbersInConn(offset);
8129 offset+=oldNumberOfNodes;
8134 * Merges nodes coincident with a given precision within all given meshes that share
8135 * the nodal connectivity array. The given meshes **can be of different** mesh
8136 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8137 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8138 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8139 * \param [in,out] meshes - a vector of meshes to update.
8140 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8141 * \throw If any of \a meshes is NULL.
8142 * \throw If the \a meshes do not share the same node coordinates array.
8143 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8145 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8149 std::set<const DataArrayDouble *> s;
8150 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8153 s.insert((*it)->getCoords());
8156 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 !";
8157 throw INTERP_KERNEL::Exception(oss.str().c_str());
8162 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 !";
8163 throw INTERP_KERNEL::Exception(oss.str().c_str());
8165 const DataArrayDouble *coo=*(s.begin());
8169 DataArrayInt *comm,*commI;
8170 coo->findCommonTuples(eps,-1,comm,commI);
8171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8172 int oldNbOfNodes=coo->getNumberOfTuples();
8174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8175 if(oldNbOfNodes==newNbOfNodes)
8177 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8178 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8180 (*it)->renumberNodesInConn(o2n->getConstPointer());
8181 (*it)->setCoords(newCoords);
8186 * 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.
8187 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8188 * \param isQuad specifies the policy of connectivity.
8189 * @ret in/out parameter in which the result will be append
8191 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8193 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8194 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8195 ret.push_back(cm.getExtrudedType());
8196 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8199 case INTERP_KERNEL::NORM_POINT1:
8201 ret.push_back(connBg[1]);
8202 ret.push_back(connBg[1]+nbOfNodesPerLev);
8205 case INTERP_KERNEL::NORM_SEG2:
8207 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8208 ret.insert(ret.end(),conn,conn+4);
8211 case INTERP_KERNEL::NORM_SEG3:
8213 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8214 ret.insert(ret.end(),conn,conn+8);
8217 case INTERP_KERNEL::NORM_QUAD4:
8219 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8220 ret.insert(ret.end(),conn,conn+8);
8223 case INTERP_KERNEL::NORM_TRI3:
8225 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8226 ret.insert(ret.end(),conn,conn+6);
8229 case INTERP_KERNEL::NORM_TRI6:
8231 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,
8232 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8233 ret.insert(ret.end(),conn,conn+15);
8236 case INTERP_KERNEL::NORM_QUAD8:
8239 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8240 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8241 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8243 ret.insert(ret.end(),conn,conn+20);
8246 case INTERP_KERNEL::NORM_POLYGON:
8248 std::back_insert_iterator< std::vector<int> > ii(ret);
8249 std::copy(connBg+1,connEnd,ii);
8251 std::reverse_iterator<const int *> rConnBg(connEnd);
8252 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8253 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8254 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8255 for(std::size_t i=0;i<nbOfRadFaces;i++)
8258 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8259 std::copy(conn,conn+4,ii);
8264 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8269 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8271 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8274 double v[3]={0.,0.,0.};
8275 std::size_t sz=std::distance(begin,end);
8280 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];
8281 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8282 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8284 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8286 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8287 // SEG3 forming a circle):
8288 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8290 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8291 for(std::size_t j=0;j<sz;j++)
8293 if (j%2) // current point i is quadratic, next point i+1 is standard
8296 ip1 = (j+1)%sz; // ip1 = "i+1"
8298 else // current point i is standard, next point i+1 is quadratic
8303 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8304 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8305 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8307 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8313 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8315 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8317 std::vector<std::pair<int,int> > edges;
8318 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8319 const int *bgFace=begin;
8320 for(std::size_t i=0;i<nbOfFaces;i++)
8322 const int *endFace=std::find(bgFace+1,end,-1);
8323 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8324 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8326 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8327 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8329 edges.push_back(p1);
8333 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8337 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8339 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8341 double vec0[3],vec1[3];
8342 std::size_t sz=std::distance(begin,end);
8344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8345 int nbOfNodes=(int)sz/2;
8346 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8347 const double *pt0=coords+3*begin[0];
8348 const double *pt1=coords+3*begin[nbOfNodes];
8349 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8350 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8353 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8355 std::size_t sz=std::distance(begin,end);
8356 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8357 std::size_t nbOfNodes(sz/2);
8358 std::copy(begin,end,(int *)tmp);
8359 for(std::size_t j=1;j<nbOfNodes;j++)
8361 begin[j]=tmp[nbOfNodes-j];
8362 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8366 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8368 std::size_t sz=std::distance(begin,end);
8370 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8371 double vec0[3],vec1[3];
8372 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8373 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];
8374 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;
8377 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8379 std::size_t sz=std::distance(begin,end);
8381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8383 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8384 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8385 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8389 * 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 )
8390 * 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
8393 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8394 * \param [in] coords the coordinates with nb of components exactly equal to 3
8395 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8396 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8397 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8399 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8401 int nbFaces=std::count(begin+1,end,-1)+1;
8402 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8403 double *vPtr=v->getPointer();
8404 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8405 double *pPtr=p->getPointer();
8406 const int *stFaceConn=begin+1;
8407 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8409 const int *endFaceConn=std::find(stFaceConn,end,-1);
8410 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8411 stFaceConn=endFaceConn+1;
8413 pPtr=p->getPointer(); vPtr=v->getPointer();
8414 DataArrayInt *comm1=0,*commI1=0;
8415 v->findCommonTuples(eps,-1,comm1,commI1);
8416 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8417 const int *comm1Ptr=comm1->getConstPointer();
8418 const int *commI1Ptr=commI1->getConstPointer();
8419 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8420 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8422 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8423 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8424 mm->finishInsertingCells();
8426 for(int i=0;i<nbOfGrps1;i++)
8428 int vecId=comm1Ptr[commI1Ptr[i]];
8429 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8430 DataArrayInt *comm2=0,*commI2=0;
8431 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8433 const int *comm2Ptr=comm2->getConstPointer();
8434 const int *commI2Ptr=commI2->getConstPointer();
8435 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8436 for(int j=0;j<nbOfGrps2;j++)
8438 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8440 res->insertAtTheEnd(begin,end);
8441 res->pushBackSilent(-1);
8445 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8446 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8447 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8448 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8449 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8450 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8453 const int *idsNodePtr=idsNode->getConstPointer();
8454 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];
8455 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8456 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8457 if(std::abs(norm)>eps)
8459 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8460 mm3->rotate(center,vec,angle);
8462 mm3->changeSpaceDimension(2);
8463 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8464 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8465 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8466 int nbOfCells=mm4->getNumberOfCells();
8467 for(int k=0;k<nbOfCells;k++)
8470 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8471 res->pushBackSilent(idsNodePtr[*work]);
8472 res->pushBackSilent(-1);
8477 res->popBackSilent();
8481 * 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
8482 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8484 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8485 * \param [in] coords coordinates expected to have 3 components.
8486 * \param [in] begin start of the nodal connectivity of the face.
8487 * \param [in] end end of the nodal connectivity (excluded) of the face.
8488 * \param [out] v the normalized vector of size 3
8489 * \param [out] p the pos of plane
8491 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8493 std::size_t nbPoints=std::distance(begin,end);
8495 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8496 double vec[3]={0.,0.,0.};
8498 bool refFound=false;
8499 for(;j<nbPoints-1 && !refFound;j++)
8501 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8502 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8503 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8504 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8508 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8511 for(std::size_t i=j;i<nbPoints-1;i++)
8514 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8515 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8516 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8517 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8520 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8521 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];
8522 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8525 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8526 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8530 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8534 * This method tries to obtain a well oriented polyhedron.
8535 * If the algorithm fails, an exception will be thrown.
8537 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8539 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8540 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8541 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8543 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8544 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8545 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8547 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8550 std::size_t smthChanged=0;
8551 for(std::size_t i=0;i<nbOfFaces;i++)
8553 endFace=std::find(bgFace+1,end,-1);
8554 nbOfEdgesInFace=std::distance(bgFace,endFace);
8558 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8560 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8561 std::pair<int,int> p2(p1.second,p1.first);
8562 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8563 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8564 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8569 std::reverse(bgFace+1,endFace);
8570 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8572 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8573 std::pair<int,int> p2(p1.second,p1.first);
8574 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8575 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8576 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8577 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8578 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8579 if(it!=edgesOK.end())
8582 edgesFinished.push_back(p1);
8585 edgesOK.push_back(p1);
8592 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8594 if(!edgesOK.empty())
8595 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8596 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8597 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8599 for(std::size_t i=0;i<nbOfFaces;i++)
8601 endFace=std::find(bgFace+1,end,-1);
8602 std::reverse(bgFace+1,endFace);
8608 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8610 int nbOfNodesExpected(skin->getNumberOfNodes());
8611 const int *n2oPtr(n2o->getConstPointer());
8612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8613 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8614 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8615 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8616 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8618 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8619 if(nbOfNodesExpected<1)
8621 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8622 *work++=n2oPtr[prevNode];
8623 for(int i=1;i<nbOfNodesExpected;i++)
8625 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8627 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8628 conn.erase(prevNode);
8631 int curNode(*(conn.begin()));
8632 *work++=n2oPtr[curNode];
8633 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8634 shar.erase(prevCell);
8637 prevCell=*(shar.begin());
8641 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8647 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8652 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8654 int nbOfNodesExpected(skin->getNumberOfNodes());
8655 int nbOfTurn(nbOfNodesExpected/2);
8656 const int *n2oPtr(n2o->getConstPointer());
8657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8658 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8659 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8660 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8661 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8662 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8663 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8664 if(nbOfNodesExpected<1)
8666 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8667 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8668 for(int i=1;i<nbOfTurn;i++)
8670 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8672 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8673 conn.erase(prevNode);
8676 int curNode(*(conn.begin()));
8677 *work=n2oPtr[curNode];
8678 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8679 shar.erase(prevCell);
8682 int curCell(*(shar.begin()));
8683 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8689 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8692 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8695 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8701 * This method makes the assumption spacedimension == meshdimension == 2.
8702 * This method works only for linear cells.
8704 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8706 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8708 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8710 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8711 int oldNbOfNodes(skin->getNumberOfNodes());
8712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8713 int nbOfNodesExpected(skin->getNumberOfNodes());
8714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8715 int nbCells(skin->getNumberOfCells());
8716 if(nbCells==nbOfNodesExpected)
8717 return buildUnionOf2DMeshLinear(skin,n2o);
8718 else if(2*nbCells==nbOfNodesExpected)
8719 return buildUnionOf2DMeshQuadratic(skin,n2o);
8721 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8725 * This method makes the assumption spacedimension == meshdimension == 3.
8726 * This method works only for linear cells.
8728 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8730 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8732 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8733 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8734 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8735 const int *conn=m->getNodalConnectivity()->getConstPointer();
8736 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8737 int nbOfCells=m->getNumberOfCells();
8738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8739 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8742 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8743 for(int i=1;i<nbOfCells;i++)
8746 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8752 * \brief Creates a graph of cell neighbors
8753 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8754 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8756 * - index: 0 3 5 6 6
8757 * - value: 1 2 3 2 3 3
8758 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8759 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8761 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8763 checkConnectivityFullyDefined();
8765 int meshDim = this->getMeshDimension();
8766 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8767 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8768 this->getReverseNodalConnectivity(revConn,indexr);
8769 const int* indexr_ptr=indexr->getConstPointer();
8770 const int* revConn_ptr=revConn->getConstPointer();
8772 const ParaMEDMEM::DataArrayInt* index;
8773 const ParaMEDMEM::DataArrayInt* conn;
8774 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8775 index=this->getNodalConnectivityIndex();
8776 int nbCells=this->getNumberOfCells();
8777 const int* index_ptr=index->getConstPointer();
8778 const int* conn_ptr=conn->getConstPointer();
8780 //creating graph arcs (cell to cell relations)
8781 //arcs are stored in terms of (index,value) notation
8784 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8785 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8787 //warning here one node have less than or equal effective number of cell with it
8788 //but cell could have more than effective nodes
8789 //because other equals nodes in other domain (with other global inode)
8790 std::vector <int> cell2cell_index(nbCells+1,0);
8791 std::vector <int> cell2cell;
8792 cell2cell.reserve(3*nbCells);
8794 for (int icell=0; icell<nbCells;icell++)
8796 std::map<int,int > counter;
8797 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8799 int inode=conn_ptr[iconn];
8800 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8802 int icell2=revConn_ptr[iconnr];
8803 std::map<int,int>::iterator iter=counter.find(icell2);
8804 if (iter!=counter.end()) (iter->second)++;
8805 else counter.insert(std::make_pair(icell2,1));
8808 for (std::map<int,int>::const_iterator iter=counter.begin();
8809 iter!=counter.end(); iter++)
8810 if (iter->second >= meshDim)
8812 cell2cell_index[icell+1]++;
8813 cell2cell.push_back(iter->first);
8818 cell2cell_index[0]=0;
8819 for (int icell=0; icell<nbCells;icell++)
8820 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8822 //filling up index and value to create skylinearray structure
8823 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8828 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8829 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8831 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8835 for(int i=0;i<nbOfNodesInCell;i++)
8836 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8837 else if(spaceDim==2)
8839 for(int i=0;i<nbOfNodesInCell;i++)
8841 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8846 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8849 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8851 int nbOfCells=getNumberOfCells();
8853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8854 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};
8855 ofs << " <" << getVTKDataSetType() << ">\n";
8856 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8857 ofs << " <PointData>\n" << pointData << std::endl;
8858 ofs << " </PointData>\n";
8859 ofs << " <CellData>\n" << cellData << std::endl;
8860 ofs << " </CellData>\n";
8861 ofs << " <Points>\n";
8862 if(getSpaceDimension()==3)
8863 _coords->writeVTK(ofs,8,"Points",byteData);
8866 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8867 coo->writeVTK(ofs,8,"Points",byteData);
8869 ofs << " </Points>\n";
8870 ofs << " <Cells>\n";
8871 const int *cPtr=_nodal_connec->getConstPointer();
8872 const int *cIPtr=_nodal_connec_index->getConstPointer();
8873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8874 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8877 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8878 int szFaceOffsets=0,szConn=0;
8879 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8882 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8885 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8886 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8890 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8891 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8892 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8893 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8894 w4=std::copy(c.begin(),c.end(),w4);
8897 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8898 types->writeVTK(ofs,8,"UInt8","types",byteData);
8899 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8900 if(szFaceOffsets!=0)
8901 {//presence of Polyhedra
8902 connectivity->reAlloc(szConn);
8903 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8905 w1=faces->getPointer();
8906 for(int i=0;i<nbOfCells;i++)
8907 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8909 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8911 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8912 for(int j=0;j<nbFaces;j++)
8914 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8915 *w1++=(int)std::distance(w6,w5);
8916 w1=std::copy(w6,w5,w1);
8920 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8922 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8923 ofs << " </Cells>\n";
8924 ofs << " </Piece>\n";
8925 ofs << " </" << getVTKDataSetType() << ">\n";
8928 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8930 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8932 { stream << " Not set !"; return ; }
8933 stream << " Mesh dimension : " << _mesh_dim << ".";
8937 { stream << " No coordinates set !"; return ; }
8938 if(!_coords->isAllocated())
8939 { stream << " Coordinates set but not allocated !"; return ; }
8940 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8941 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8942 if(!_nodal_connec_index)
8943 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8944 if(!_nodal_connec_index->isAllocated())
8945 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8946 int lgth=_nodal_connec_index->getNumberOfTuples();
8947 int cpt=_nodal_connec_index->getNumberOfComponents();
8948 if(cpt!=1 || lgth<1)
8950 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8953 std::string MEDCouplingUMesh::getVTKDataSetType() const
8955 return std::string("UnstructuredGrid");
8958 std::string MEDCouplingUMesh::getVTKFileExtension() const
8960 return std::string("vtu");
8964 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8965 * returns a result mesh constituted by polygons.
8966 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8967 * all nodes from m2.
8968 * The meshes should be in 2D space. In
8969 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8971 * \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
8972 * 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)
8973 * \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
8974 * 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)
8975 * \param [in] eps - precision used to detect coincident mesh entities.
8976 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8977 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8978 * this array using decrRef() as it is no more needed.
8979 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8980 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8981 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8982 * any cell of \a m2. The caller is to delete this array using decrRef() as
8983 * it is no more needed.
8984 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8985 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8986 * is no more needed.
8987 * \throw If the coordinates array is not set in any of the meshes.
8988 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8989 * \throw If any of the meshes is not a 2D mesh in 2D space.
8991 * \sa conformize2D, mergeNodes
8993 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8994 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8997 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8998 m1->checkFullyDefined();
8999 m2->checkFullyDefined();
9000 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9001 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
9003 // Step 1: compute all edge intersections (new nodes)
9004 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9005 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9006 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9007 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9008 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9009 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9010 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9011 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9013 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9015 // Step 2: re-order newly created nodes according to the ordering found in m2
9016 std::vector< std::vector<int> > intersectEdge2;
9017 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9018 subDiv2.clear(); dd5=0; dd6=0;
9021 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9022 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9023 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9024 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9026 // Step 4: Prepare final result:
9027 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9028 addCooDa->alloc((int)(addCoo.size())/2,2);
9029 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9030 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9031 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9032 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9033 std::vector<const DataArrayDouble *> coordss(4);
9034 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9035 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9036 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9037 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9039 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9041 ret->setConnectivity(conn,connI,true);
9042 ret->setCoords(coo);
9043 cellNb1=c1.retn(); cellNb2=c2.retn();
9049 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9051 if(candidates.empty())
9053 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9055 const std::vector<int>& pool(intersectEdge1[*it]);
9056 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9057 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9062 tmp[0]=stop; tmp[1]=start;
9063 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9072 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,
9073 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9075 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9076 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9077 int nCells(mesh1D->getNumberOfCells());
9078 if(nCells!=(int)intersectEdge2.size())
9079 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9080 const DataArrayDouble *coo2(mesh1D->getCoords());
9081 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9082 const double *coo2Ptr(coo2->begin());
9083 int offset1(coords1->getNumberOfTuples());
9084 int offset2(offset1+coo2->getNumberOfTuples());
9085 int offset3(offset2+addCoo.size()/2);
9086 std::vector<double> addCooQuad;
9087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9088 int tmp[4],cicnt(0),kk(0);
9089 for(int i=0;i<nCells;i++)
9091 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9092 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9093 const std::vector<int>& subEdges(intersectEdge2[i]);
9094 int nbSubEdge(subEdges.size()/2);
9095 for(int j=0;j<nbSubEdge;j++,kk++)
9097 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));
9098 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9099 INTERP_KERNEL::Edge *e2Ptr(e2);
9100 std::map<int,int>::const_iterator itm;
9101 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9103 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9104 itm=mergedNodes.find(subEdges[2*j]);
9105 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9106 itm=mergedNodes.find(subEdges[2*j+1]);
9107 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9108 tmp[3]=offset3+(int)addCooQuad.size()/2;
9110 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9112 cOut->insertAtTheEnd(tmp,tmp+4);
9113 ciOut->pushBackSilent(cicnt);
9117 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9118 itm=mergedNodes.find(subEdges[2*j]);
9119 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9120 itm=mergedNodes.find(subEdges[2*j+1]);
9121 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9123 cOut->insertAtTheEnd(tmp,tmp+3);
9124 ciOut->pushBackSilent(cicnt);
9127 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9129 idsInRetColinear->pushBackSilent(kk);
9130 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9135 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9136 ret->setConnectivity(cOut,ciOut,true);
9137 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9138 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9139 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9140 std::vector<const DataArrayDouble *> coordss(4);
9141 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9142 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9143 ret->setCoords(arr);
9147 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9149 std::vector<int> allEdges;
9150 for(const int *it2(descBg);it2!=descEnd;it2++)
9152 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9154 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9156 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9158 std::size_t nb(allEdges.size());
9160 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9161 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9162 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9163 ret->setCoords(coords);
9164 ret->allocateCells(1);
9165 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9166 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9167 connOut[kk]=allEdges[2*kk];
9168 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9172 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9174 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9175 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9177 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9178 if(sz!=std::distance(descBg,descEnd))
9179 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9180 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9181 std::vector<int> allEdges,centers;
9182 const double *coordsPtr(coords->begin());
9183 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9184 int offset(coords->getNumberOfTuples());
9185 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9187 INTERP_KERNEL::NormalizedCellType typeOfSon;
9188 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9189 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9191 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9193 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9195 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9197 {//the current edge has been subsplit -> create corresponding centers.
9198 std::size_t nbOfCentersToAppend(edge1.size()/2);
9199 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9200 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9201 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9202 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9205 const double *aa(coordsPtr+2*(*it3++));
9206 const double *bb(coordsPtr+2*(*it3++));
9207 ee->getMiddleOfPoints(aa,bb,tmpp);
9208 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9209 centers.push_back(offset+k);
9213 std::size_t nb(allEdges.size());
9215 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9216 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9217 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9219 ret->setCoords(coords);
9222 addCoo->rearrange(2);
9223 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9224 ret->setCoords(addCoo);
9226 ret->allocateCells(1);
9227 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9228 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9229 connOut[kk]=allEdges[2*kk];
9230 connOut.insert(connOut.end(),centers.begin(),centers.end());
9231 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9236 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9239 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9241 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9243 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9244 if(!cm.isQuadratic())
9245 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9247 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9250 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9253 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9255 const INTERP_KERNEL::Edge *ee(*it);
9256 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9260 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9263 const double *coo(mesh2D->getCoords()->begin());
9264 std::size_t sz(conn.size());
9265 std::vector<double> addCoo;
9266 std::vector<int> conn2(conn);
9267 int offset(mesh2D->getNumberOfNodes());
9268 for(std::size_t i=0;i<sz;i++)
9271 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9272 addCoo.insert(addCoo.end(),tmp,tmp+2);
9273 conn2.push_back(offset+(int)i);
9275 mesh2D->getCoords()->rearrange(1);
9276 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9277 mesh2D->getCoords()->rearrange(2);
9278 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9283 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9285 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9286 * a set of edges defined in \a splitMesh1D.
9288 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9289 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9291 std::size_t nb(edge1Bis.size()/2);
9292 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9293 int iEnd(splitMesh1D->getNumberOfCells());
9295 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9297 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9298 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9299 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9302 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9303 out0.resize(1); out1.resize(1);
9304 std::vector<int>& connOut(out0[0]);
9305 connOut.resize(nbOfEdgesOf2DCellSplit);
9306 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9307 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9308 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9310 connOut[kk]=edge1Bis[2*kk];
9311 edgesPtr[kk]=edge1BisPtr[2*kk];
9316 // [i,iEnd[ contains the
9317 out0.resize(2); out1.resize(2);
9318 std::vector<int>& connOutLeft(out0[0]);
9319 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9320 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9321 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9322 for(std::size_t k=ii;k<jj+1;k++)
9323 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9324 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9325 for(int ik=0;ik<iEnd;ik++)
9327 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9328 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9331 for(int ik=iEnd-1;ik>=0;ik--)
9332 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9333 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9334 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9335 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9336 for(int ik=0;ik<iEnd;ik++)
9337 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9338 eright.insert(eright.end(),ees.begin(),ees.end());
9350 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9352 std::vector<int> _edges;
9353 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9356 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9358 std::size_t nbe(edges.size());
9359 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9360 for(std::size_t i=0;i<nbe;i++)
9362 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9363 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9365 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9366 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9367 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9373 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9374 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9375 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9376 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9377 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9381 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9382 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9387 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9389 const MEDCouplingUMesh *mesh(_mesh);
9395 { _left++; _right++; return ; }
9398 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9399 if((isLeft && isRight) || (!isLeft && !isRight))
9400 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9411 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9412 if((isLeft && isRight) || (!isLeft && !isRight))
9413 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9428 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9430 const MEDCouplingUMesh *mesh(_mesh);
9433 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9436 {// not fully splitting cell case
9437 if(mesh2D->getNumberOfCells()==1)
9438 {//little optimization. 1 cell no need to find in which cell mesh is !
9439 neighbors[0]=offset; neighbors[1]=offset;
9444 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9445 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9447 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9448 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9453 class VectorOfCellInfo
9456 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9457 std::size_t size() const { return _pool.size(); }
9458 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9459 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);
9460 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9461 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9462 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9463 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9465 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9466 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9467 const CellInfo& get(int pos) const;
9468 CellInfo& get(int pos);
9470 std::vector<CellInfo> _pool;
9471 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9472 std::vector<EdgeInfo> _edge_info;
9475 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9477 _pool[0]._edges=edges;
9478 _pool[0]._edges_ptr=edgesPtr;
9481 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9484 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9487 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9489 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9490 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9491 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9494 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)
9496 get(pos);//to check pos
9497 bool isFast(pos==0 && _pool.size()==1);
9498 std::size_t sz(edges.size());
9499 // dealing with edges
9501 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9503 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9505 std::vector<CellInfo> pool(_pool.size()-1+sz);
9506 for(int i=0;i<pos;i++)
9508 for(std::size_t j=0;j<sz;j++)
9509 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9510 for(int i=pos+1;i<(int)_pool.size();i++)
9511 pool[i+sz-1]=_pool[i];
9515 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9523 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9526 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9530 if(pos<_ze_mesh->getNumberOfCells()-1)
9532 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9535 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9536 for(std::size_t j=0;j<ms2.size();j++)
9538 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9541 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9543 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9546 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9549 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9551 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9553 if((*it).isInMyRange(pos))
9556 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9559 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9561 get(pos);//to check;
9562 if(_edge_info.empty())
9564 std::size_t sz(_edge_info.size()-1);
9565 for(std::size_t i=0;i<sz;i++)
9566 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9569 const CellInfo& VectorOfCellInfo::get(int pos) const
9571 if(pos<0 || pos>=(int)_pool.size())
9572 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9576 CellInfo& VectorOfCellInfo::get(int pos)
9578 if(pos<0 || pos>=(int)_pool.size())
9579 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9585 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9586 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9588 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9590 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9592 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9594 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9595 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9597 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9598 if(nbCellsInSplitMesh1D==0)
9599 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9600 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9601 std::size_t nb(allEdges.size()),jj;
9603 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9604 std::vector<int> edge1Bis(nb*2);
9605 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9606 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9607 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9608 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9609 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9611 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9612 int *idsLeftRightPtr(idsLeftRight->getPointer());
9613 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9614 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9615 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9617 for(;iEnd<nbCellsInSplitMesh1D;)
9619 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9625 if(iEnd<nbCellsInSplitMesh1D)
9628 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9629 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9631 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9632 retTmp->setCoords(splitMesh1D->getCoords());
9633 retTmp->allocateCells();
9635 std::vector< std::vector<int> > out0;
9636 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9638 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9639 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9640 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9641 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9645 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9646 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9647 return pool.getZeMesh().retn();
9650 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9651 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9654 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9656 std::vector<int> allEdges;
9657 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9658 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9660 int edgeId(std::abs(*it)-1);
9661 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9662 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9663 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9665 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9667 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9668 std::size_t sz(edge1.size());
9669 for(std::size_t cnt=0;cnt<sz;cnt++)
9670 allEdgesPtr.push_back(ee);
9673 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9676 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9678 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9679 {//easy case comparison not
9680 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9682 else if(typ1.isQuadratic() && typ2.isQuadratic())
9684 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9687 if(conn1[2]==conn2[2])
9689 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9690 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9694 {//only one is quadratic
9695 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9698 const double *a(0),*bb(0),*be(0);
9699 if(typ1.isQuadratic())
9701 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9705 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9707 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9708 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9714 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9715 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9717 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9719 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9721 if(candidatesIn2DEnd==candidatesIn2DBg)
9722 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9723 const double *coo(mesh2DSplit->getCoords()->begin());
9724 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9725 return *candidatesIn2DBg;
9726 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9727 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9728 if(cellIdInMesh1DSplitRelative<0)
9729 cur1D->changeOrientationOfCells();
9730 const int *c1D(cur1D->getNodalConnectivity()->begin());
9731 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9732 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9734 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9735 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9736 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9737 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9738 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9739 for(unsigned it2=0;it2<sz;it2++)
9741 INTERP_KERNEL::NormalizedCellType typeOfSon;
9742 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9743 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9744 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9748 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9754 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9755 * 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
9756 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9757 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9759 * \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
9760 * 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)
9761 * \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
9762 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9763 * \param [in] eps - precision used to perform intersections and localization operations.
9764 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9765 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9766 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9767 * 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.
9768 * \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
9769 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9770 * 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.
9772 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9774 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9776 if(!mesh2D || !mesh1D)
9777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9778 mesh2D->checkFullyDefined();
9779 mesh1D->checkFullyDefined();
9780 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9781 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9783 // Step 1: compute all edge intersections (new nodes)
9784 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9785 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9786 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9787 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9789 // Build desc connectivity
9790 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9791 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9792 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9793 std::map<int,int> mergedNodes;
9794 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9795 // use mergeNodes to fix intersectEdge1
9796 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9798 std::size_t n((*it0).size()/2);
9799 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9800 std::map<int,int>::const_iterator it1;
9801 it1=mergedNodes.find(eltStart);
9802 if(it1!=mergedNodes.end())
9803 (*it0)[0]=(*it1).second;
9804 it1=mergedNodes.find(eltEnd);
9805 if(it1!=mergedNodes.end())
9806 (*it0)[2*n-1]=(*it1).second;
9809 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9810 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9811 // Step 2: re-order newly created nodes according to the ordering found in m2
9812 std::vector< std::vector<int> > intersectEdge2;
9813 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9815 // Step 3: compute splitMesh1D
9816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9818 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9819 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9822 // deal with cells in mesh2D that are not cut but only some of their edges are
9823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9824 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9825 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9826 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
9827 if(!idsInDesc2DToBeRefined->empty())
9829 DataArrayInt *out0(0),*outi0(0);
9830 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9833 out0s=out0s->buildUnique();
9837 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9838 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9840 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9843 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9844 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9847 if((DataArrayInt *)out0s)
9848 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9849 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9850 // OK all is ready to insert in ret2 mesh
9851 if(!untouchedCells->empty())
9852 {// the most easy part, cells in mesh2D not impacted at all
9853 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9854 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9855 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9857 if((DataArrayInt *)out0s)
9858 {// here dealing with cells in out0s but not in cellsToBeModified
9859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9860 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9861 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9863 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9864 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9866 int offset(ret2->getNumberOfTuples());
9867 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9869 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9870 int kk(0),*ret3ptr(partOfRet3->getPointer());
9871 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9873 int faceId(std::abs(*it)-1);
9874 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9876 int tmp(fewModifiedCells->locateValue(*it2));
9879 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9880 ret3ptr[2*kk]=tmp+offset;
9881 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9882 ret3ptr[2*kk+1]=tmp+offset;
9885 {//the current edge is shared by a 2D cell that will be split just after
9886 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9887 ret3ptr[2*kk]=-(*it2+1);
9888 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9889 ret3ptr[2*kk+1]=-(*it2+1);
9893 m1Desc->setCoords(ret1->getCoords());
9894 ret1NonCol->setCoords(ret1->getCoords());
9895 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9896 if(!outMesh2DSplit.empty())
9898 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9899 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9900 (*itt)->setCoords(da);
9903 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9904 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9907 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9909 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9911 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));
9912 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9913 outMesh2DSplit.push_back(splitOfOneCell);
9914 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9915 ret2->pushBackSilent(*it);
9918 std::size_t nbOfMeshes(outMesh2DSplit.size());
9919 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9920 for(std::size_t i=0;i<nbOfMeshes;i++)
9921 tmp[i]=outMesh2DSplit[i];
9923 ret1->getCoords()->setInfoOnComponents(compNames);
9924 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9925 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9927 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9928 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9930 int old2DCellId(-ret3->getIJ(*it,0)-1);
9931 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9932 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
9934 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9937 splitMesh1D=ret1.retn();
9938 splitMesh2D=ret2D.retn();
9939 cellIdInMesh2D=ret2.retn();
9940 cellIdInMesh1D=ret3.retn();
9944 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9945 * (newly created) nodes corresponding to the edge intersections.
9947 * @param[out] cr, crI connectivity of the resulting mesh
9948 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9949 * TODO: describe input parameters
9951 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9952 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9953 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9954 const std::vector<double>& addCoords,
9955 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9957 static const int SPACEDIM=2;
9958 const double *coo1(m1->getCoords()->getConstPointer());
9959 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9960 int offset1(m1->getNumberOfNodes());
9961 const double *coo2(m2->getCoords()->getConstPointer());
9962 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9963 int offset2(offset1+m2->getNumberOfNodes());
9964 int offset3(offset2+((int)addCoords.size())/2);
9965 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9966 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9967 // Here a BBTree on 2D-cells, not on segments:
9968 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9969 int ncell1(m1->getNumberOfCells());
9971 for(int i=0;i<ncell1;i++)
9973 std::vector<int> candidates2;
9974 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9975 std::map<INTERP_KERNEL::Node *,int> mapp;
9976 std::map<int,INTERP_KERNEL::Node *> mappRev;
9977 INTERP_KERNEL::QuadraticPolygon pol1;
9978 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9979 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9980 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9981 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9982 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9983 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9984 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9986 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
9987 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9988 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9989 for(it1.first();!it1.finished();it1.next())
9990 edges1.insert(it1.current()->getPtr());
9992 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9993 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9995 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9997 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9998 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9999 // Complete mapping with elements coming from the current cell it2 in mesh2:
10000 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10001 // pol2 is the new QP in the final merged result.
10002 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10003 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10006 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10008 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10009 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10010 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10011 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10013 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10014 // by m2 but that we still want to keep in the final result.
10015 if(!edges1.empty())
10019 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10021 catch(INTERP_KERNEL::Exception& e)
10023 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();
10024 throw INTERP_KERNEL::Exception(oss.str().c_str());
10027 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10028 (*it).second->decrRef();
10033 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10034 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10035 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10036 * The caller is to deal with the resulting DataArrayInt.
10037 * \throw If the coordinate array is not set.
10038 * \throw If the nodal connectivity of the cells is not defined.
10039 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10040 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10042 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10044 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10046 checkFullyDefined();
10047 if(getMeshDimension()!=1)
10048 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10050 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10051 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10053 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10054 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10055 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10057 const int * dsi(_dsi->getConstPointer());
10058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10060 if (dsii->getNumberOfTuples())
10061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10063 int nc(getNumberOfCells());
10064 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10065 result->alloc(nc,1);
10067 // set of edges not used so far
10068 std::set<int> edgeSet;
10069 for (int i=0; i<nc; edgeSet.insert(i), i++);
10073 // while we have points with only one neighbor segments
10076 std::list<int> linePiece;
10077 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10078 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10080 // Fill the list forward (resp. backward) from the start segment:
10081 int activeSeg = startSeg;
10082 int prevPointId = -20;
10084 while (!edgeSet.empty())
10086 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10089 linePiece.push_back(activeSeg);
10091 linePiece.push_front(activeSeg);
10092 edgeSet.erase(activeSeg);
10095 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10096 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10097 if (dsi[ptId] == 1) // hitting the end of the line
10099 prevPointId = ptId;
10100 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10101 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10104 // Done, save final piece into DA:
10105 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10106 newIdx += linePiece.size();
10108 // identify next valid start segment (one which is not consumed)
10109 if(!edgeSet.empty())
10110 startSeg = *(edgeSet.begin());
10112 while (!edgeSet.empty());
10113 return result.retn();
10118 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10120 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10121 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10123 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10124 int v((*it).second);
10125 if(v==forbVal0 || v==forbVal1)
10127 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10128 isect.push_back(v);
10131 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10136 bool presenceOfOn(false);
10137 for(int i=0;i<sz;i++)
10139 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10140 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10142 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10143 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10145 return presenceOfOn;
10151 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10152 * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10153 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10154 * a minimal creation of new nodes is wanted.
10155 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10156 * nodes if a SEG3 is split without information of middle.
10157 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10158 * avoid to have a non conform mesh.
10160 * \return int - the number of new nodes created (in most of cases 0).
10162 * \throw If \a this is not coherent.
10163 * \throw If \a this has not spaceDim equal to 2.
10164 * \throw If \a this has not meshDim equal to 2.
10165 * \throw If some subcells needed to be split are orphan.
10166 * \sa MEDCouplingUMesh::conformize2D
10168 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10170 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10171 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10172 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10173 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10175 if(midOpt==0 && midOptI==0)
10177 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10180 else if(midOpt!=0 && midOptI!=0)
10181 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10183 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10187 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10188 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10189 * 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
10190 * 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).
10191 * 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.
10193 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10194 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10196 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10197 * This method expects that all nodes in \a this are not closer than \a eps.
10198 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10200 * \param [in] eps the relative error to detect merged edges.
10201 * \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
10202 * that the user is expected to deal with.
10204 * \throw If \a this is not coherent.
10205 * \throw If \a this has not spaceDim equal to 2.
10206 * \throw If \a this has not meshDim equal to 2.
10207 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10209 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10211 static const int SPACEDIM=2;
10213 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10214 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10216 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10217 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10218 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10219 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10220 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10221 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10222 std::vector<double> addCoo;
10223 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10224 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10225 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10226 for(int i=0;i<nDescCell;i++)
10228 std::vector<int> candidates;
10229 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10230 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10233 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10234 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10235 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10236 INTERP_KERNEL::MergePoints merge;
10237 INTERP_KERNEL::QuadraticPolygon c1,c2;
10238 e1->intersectWith(e2,merge,c1,c2);
10239 e1->decrRef(); e2->decrRef();
10240 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10241 overlapEdge[i].push_back(*it);
10242 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10243 overlapEdge[*it].push_back(i);
10246 // splitting done. sort intersect point in intersectEdge.
10247 std::vector< std::vector<int> > middle(nDescCell);
10248 int nbOf2DCellsToBeSplit(0);
10249 bool middleNeedsToBeUsed(false);
10250 std::vector<bool> cells2DToTreat(nDescCell,false);
10251 for(int i=0;i<nDescCell;i++)
10253 std::vector<int>& isect(intersectEdge[i]);
10254 int sz((int)isect.size());
10257 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10258 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10259 e->sortSubNodesAbs(coords,isect);
10264 int idx0(rdi[i]),idx1(rdi[i+1]);
10266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10267 if(!cells2DToTreat[rd[idx0]])
10269 cells2DToTreat[rd[idx0]]=true;
10270 nbOf2DCellsToBeSplit++;
10272 // try to reuse at most eventual 'middle' of SEG3
10273 std::vector<int>& mid(middle[i]);
10274 mid.resize(sz+1,-1);
10275 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10277 middleNeedsToBeUsed=true;
10278 const std::vector<int>& candidates(overlapEdge[i]);
10279 std::vector<int> trueCandidates;
10280 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10281 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10282 trueCandidates.push_back(*itc);
10283 int stNode(c[ci[i]+1]),endNode(isect[0]);
10284 for(int j=0;j<sz+1;j++)
10286 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10288 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10289 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10290 { mid[j]=*itc; break; }
10293 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10299 if(nbOf2DCellsToBeSplit==0)
10302 int *retPtr(ret->getPointer());
10303 for(int i=0;i<nCell;i++)
10304 if(cells2DToTreat[i])
10307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10308 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10309 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10310 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10311 if(middleNeedsToBeUsed)
10312 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10313 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10314 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10315 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.
10316 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10318 bool areNodesMerged; int newNbOfNodes;
10319 if(nbOfNodesCreated!=0)
10320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10326 * 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.
10327 * 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).
10328 * 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
10329 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10330 * 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
10331 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10333 * 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
10334 * using new instance, idem for coordinates.
10336 * 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.
10338 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10340 * \throw If \a this is not coherent.
10341 * \throw If \a this has not spaceDim equal to 2.
10342 * \throw If \a this has not meshDim equal to 2.
10344 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10346 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10350 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10351 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10352 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10353 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10354 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10355 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10357 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10358 const double *coords(_coords->begin());
10359 int *newciptr(newci->getPointer());
10360 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10362 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10363 ret->pushBackSilent(i);
10364 newciptr[1]=newc->getNumberOfTuples();
10369 if(!appendedCoords->empty())
10371 appendedCoords->rearrange(2);
10372 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10374 setCoords(newCoords);
10377 setConnectivity(newc,newci,true);
10382 * \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.
10383 * 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.
10384 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10385 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10386 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10387 * \param [out] addCoo - nodes to be append at the end
10388 * \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.
10390 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10391 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)
10393 static const int SPACEDIM=2;
10394 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10395 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10396 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10397 // Build BB tree of all edges in the tool mesh (second mesh)
10398 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10399 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10400 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10401 intersectEdge1.resize(nDescCell1);
10402 colinear2.resize(nDescCell2);
10403 subDiv2.resize(nDescCell2);
10404 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10406 std::vector<int> candidates1(1);
10407 int offset1(m1Desc->getNumberOfNodes());
10408 int offset2(offset1+m2Desc->getNumberOfNodes());
10409 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10411 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10412 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10413 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10415 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10416 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10417 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10419 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10420 // 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
10421 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10422 std::set<INTERP_KERNEL::Node *> nodes;
10423 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10424 std::size_t szz(nodes.size());
10425 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10426 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10427 for(std::size_t iii=0;iii<szz;iii++,itt++)
10428 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10429 // end of protection
10430 // Performs egde cutting:
10431 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10436 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10437 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10442 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10443 * It builds the descending connectivity of the two meshes, and then using a binary tree
10444 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10445 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10447 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10448 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10449 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10450 std::vector<double>& addCoo,
10451 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10453 // Build desc connectivity
10454 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10455 desc2=DataArrayInt::New();
10456 descIndx2=DataArrayInt::New();
10457 revDesc2=DataArrayInt::New();
10458 revDescIndx2=DataArrayInt::New();
10459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10461 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10462 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10463 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10464 std::map<int,int> notUsedMap;
10465 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10466 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10467 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10471 * This method performs the 2nd step of Partition of 2D mesh.
10472 * This method has 4 inputs :
10473 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10474 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10475 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10476 * 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'
10477 * Nodes end up lying consecutively on a cutted edge.
10478 * \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.
10479 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10480 * \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.
10481 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10482 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10484 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10485 const std::vector<double>& addCoo,
10486 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10488 int offset1=m1->getNumberOfNodes();
10489 int ncell=m2->getNumberOfCells();
10490 const int *c=m2->getNodalConnectivity()->getConstPointer();
10491 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10492 const double *coo=m2->getCoords()->getConstPointer();
10493 const double *cooBis=m1->getCoords()->getConstPointer();
10494 int offset2=offset1+m2->getNumberOfNodes();
10495 intersectEdge.resize(ncell);
10496 for(int i=0;i<ncell;i++,cI++)
10498 const std::vector<int>& divs=subDiv[i];
10499 int nnode=cI[1]-cI[0]-1;
10500 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10501 std::map<INTERP_KERNEL::Node *, int> mapp22;
10502 for(int j=0;j<nnode;j++)
10504 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10505 int nnid=c[(*cI)+j+1];
10506 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10507 mapp22[nn]=nnid+offset1;
10509 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10510 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10511 ((*it).second.first)->decrRef();
10512 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10513 std::map<INTERP_KERNEL::Node *,int> mapp3;
10514 for(std::size_t j=0;j<divs.size();j++)
10517 INTERP_KERNEL::Node *tmp=0;
10519 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10520 else if(id<offset2)
10521 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10523 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10527 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10528 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10535 * 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).
10536 * 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
10537 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10538 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10539 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10540 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10541 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10542 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10543 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10544 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10545 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10546 * \param [out] cut3DSuf input/output param.
10548 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10549 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10550 const int *desc, const int *descIndx,
10551 std::vector< std::pair<int,int> >& cut3DSurf)
10553 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10554 int nbOf3DSurfCell=(int)cut3DSurf.size();
10555 for(int i=0;i<nbOf3DSurfCell;i++)
10557 std::vector<int> res;
10558 int offset=descIndx[i];
10559 int nbOfSeg=descIndx[i+1]-offset;
10560 for(int j=0;j<nbOfSeg;j++)
10562 int edgeId=desc[offset+j];
10563 int status=cut3DCurve[edgeId];
10567 res.push_back(status);
10570 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10571 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10579 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10585 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10586 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10589 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10593 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10598 {// case when plane is on a multi colinear edge of a polyhedron
10599 if((int)res.size()==2*nbOfSeg)
10601 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10604 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10611 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10612 * 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).
10613 * 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
10614 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10615 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10616 * \param desc is the descending connectivity 3D->3DSurf
10617 * \param descIndx is the descending connectivity index 3D->3DSurf
10619 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10620 const int *desc, const int *descIndx,
10621 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10623 checkFullyDefined();
10624 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10626 const int *nodal3D=_nodal_connec->getConstPointer();
10627 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10628 int nbOfCells=getNumberOfCells();
10629 for(int i=0;i<nbOfCells;i++)
10631 std::map<int, std::set<int> > m;
10632 int offset=descIndx[i];
10633 int nbOfFaces=descIndx[i+1]-offset;
10636 for(int j=0;j<nbOfFaces;j++)
10638 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10639 if(p.first!=-1 && p.second!=-1)
10643 start=p.first; end=p.second;
10644 m[p.first].insert(p.second);
10645 m[p.second].insert(p.first);
10649 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10650 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10651 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10652 INTERP_KERNEL::NormalizedCellType cmsId;
10653 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10654 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10655 for(unsigned k=0;k<nbOfNodesSon;k++)
10657 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10658 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10665 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10669 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10670 const std::set<int>& s=(*it).second;
10671 std::set<int> s2; s2.insert(prev);
10673 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10676 int val=*s3.begin();
10677 conn.push_back(start);
10684 conn.push_back(end);
10687 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10688 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10689 cellIds->pushBackSilent(i);
10695 * 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
10696 * 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
10697 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10698 * 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
10699 * 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.
10701 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10703 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10705 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10708 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10709 if(cm.getDimension()==2)
10711 const int *node=nodalConnBg+1;
10712 int startNode=*node++;
10713 double refX=coords[2*startNode];
10714 for(;node!=nodalConnEnd;node++)
10716 if(coords[2*(*node)]<refX)
10719 refX=coords[2*startNode];
10722 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10726 double angle0=-M_PI/2;
10731 double angleNext=0.;
10732 while(nextNode!=startNode)
10736 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10738 if(*node!=tmpOut.back() && *node!=prevNode)
10740 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10741 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10746 res=angle0-angleM+2.*M_PI;
10755 if(nextNode!=startNode)
10757 angle0=angleNext-M_PI;
10760 prevNode=tmpOut.back();
10761 tmpOut.push_back(nextNode);
10764 std::vector<int> tmp3(2*(sz-1));
10765 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10766 std::copy(nodalConnBg+1,nodalConnEnd,it);
10767 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10769 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10772 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10774 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10779 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10780 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10792 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10793 * 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.
10795 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10796 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10797 * \param [in,out] arr array in which the remove operation will be done.
10798 * \param [in,out] arrIndx array in the remove operation will modify
10799 * \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])
10800 * \return true if \b arr and \b arrIndx have been modified, false if not.
10802 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10804 if(!arrIndx || !arr)
10805 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10806 if(offsetForRemoval<0)
10807 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10808 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10809 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10810 int *arrIPtr=arrIndx->getPointer();
10812 int previousArrI=0;
10813 const int *arrPtr=arr->getConstPointer();
10814 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10815 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10817 if(*arrIPtr-previousArrI>offsetForRemoval)
10819 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10821 if(s.find(*work)==s.end())
10822 arrOut.push_back(*work);
10825 previousArrI=*arrIPtr;
10826 *arrIPtr=(int)arrOut.size();
10828 if(arr->getNumberOfTuples()==(int)arrOut.size())
10830 arr->alloc((int)arrOut.size(),1);
10831 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10836 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10837 * (\ref numbering-indirect).
10838 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10839 * The selection of extraction is done standardly in new2old format.
10840 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10842 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10843 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10844 * \param [in] arrIn arr origin array from which the extraction will be done.
10845 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10846 * \param [out] arrOut the resulting array
10847 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10848 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10850 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10851 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10853 if(!arrIn || !arrIndxIn)
10854 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10855 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10856 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10858 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10859 const int *arrInPtr=arrIn->getConstPointer();
10860 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10861 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10864 int maxSizeOfArr=arrIn->getNumberOfTuples();
10865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10867 arrIo->alloc((int)(sz+1),1);
10868 const int *idsIt=idsOfSelectBg;
10869 int *work=arrIo->getPointer();
10872 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10874 if(*idsIt>=0 && *idsIt<nbOfGrps)
10875 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10878 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10879 throw INTERP_KERNEL::Exception(oss.str().c_str());
10885 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10886 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10887 throw INTERP_KERNEL::Exception(oss.str().c_str());
10890 arro->alloc(lgth,1);
10891 work=arro->getPointer();
10892 idsIt=idsOfSelectBg;
10893 for(std::size_t i=0;i<sz;i++,idsIt++)
10895 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10896 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10899 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10900 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10901 throw INTERP_KERNEL::Exception(oss.str().c_str());
10904 arrOut=arro.retn();
10905 arrIndexOut=arrIo.retn();
10909 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10910 * (\ref numbering-indirect).
10911 * 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 ).
10912 * The selection of extraction is done standardly in new2old format.
10913 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10915 * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10916 * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10917 * \param [in] idsOfSelectStep
10918 * \param [in] arrIn arr origin array from which the extraction will be done.
10919 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10920 * \param [out] arrOut the resulting array
10921 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10922 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10924 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10925 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10927 if(!arrIn || !arrIndxIn)
10928 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10929 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10930 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10932 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10933 const int *arrInPtr=arrIn->getConstPointer();
10934 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10935 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10938 int maxSizeOfArr=arrIn->getNumberOfTuples();
10939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10940 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10941 arrIo->alloc((int)(sz+1),1);
10942 int idsIt=idsOfSelectStart;
10943 int *work=arrIo->getPointer();
10946 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10948 if(idsIt>=0 && idsIt<nbOfGrps)
10949 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10952 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10953 throw INTERP_KERNEL::Exception(oss.str().c_str());
10959 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10960 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10961 throw INTERP_KERNEL::Exception(oss.str().c_str());
10964 arro->alloc(lgth,1);
10965 work=arro->getPointer();
10966 idsIt=idsOfSelectStart;
10967 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10969 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10970 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10973 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10974 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10975 throw INTERP_KERNEL::Exception(oss.str().c_str());
10978 arrOut=arro.retn();
10979 arrIndexOut=arrIo.retn();
10983 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10984 * 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
10985 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10986 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10988 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10989 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10990 * \param [in] arrIn arr origin array from which the extraction will be done.
10991 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10992 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10993 * \param [in] srcArrIndex index array of \b srcArr
10994 * \param [out] arrOut the resulting array
10995 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10997 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10999 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11000 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11001 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11003 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11004 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11005 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11006 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11007 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11008 std::vector<bool> v(nbOfTuples,true);
11010 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11011 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11012 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11014 if(*it>=0 && *it<nbOfTuples)
11017 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11021 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11022 throw INTERP_KERNEL::Exception(oss.str().c_str());
11025 srcArrIndexPtr=srcArrIndex->getConstPointer();
11026 arrIo->alloc(nbOfTuples+1,1);
11027 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11028 const int *arrInPtr=arrIn->getConstPointer();
11029 const int *srcArrPtr=srcArr->getConstPointer();
11030 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11031 int *arroPtr=arro->getPointer();
11032 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11036 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11037 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11041 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11042 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11043 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11046 arrOut=arro.retn();
11047 arrIndexOut=arrIo.retn();
11051 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11052 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11054 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11055 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11056 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11057 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11058 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11059 * \param [in] srcArrIndex index array of \b srcArr
11061 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11063 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11064 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11066 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11067 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11068 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11069 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11070 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11071 int *arrInOutPtr=arrInOut->getPointer();
11072 const int *srcArrPtr=srcArr->getConstPointer();
11073 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11075 if(*it>=0 && *it<nbOfTuples)
11077 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11078 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11081 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] !";
11082 throw INTERP_KERNEL::Exception(oss.str().c_str());
11087 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11088 throw INTERP_KERNEL::Exception(oss.str().c_str());
11094 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11095 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11096 * 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]].
11097 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11098 * A negative value in \b arrIn means that it is ignored.
11099 * 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.
11101 * \param [in] arrIn arr origin array from which the extraction will be done.
11102 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11103 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11104 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11106 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11108 int seed=0,nbOfDepthPeelingPerformed=0;
11109 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11113 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11114 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11115 * 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]].
11116 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11117 * A negative value in \b arrIn means that it is ignored.
11118 * 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.
11119 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11120 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11121 * \param [in] arrIn arr origin array from which the extraction will be done.
11122 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11123 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11124 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11125 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11126 * \sa MEDCouplingUMesh::partitionBySpreadZone
11128 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11130 nbOfDepthPeelingPerformed=0;
11132 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11133 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11136 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11140 std::vector<bool> fetched(nbOfTuples,false);
11141 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11144 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11146 nbOfDepthPeelingPerformed=0;
11147 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11148 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11149 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11150 std::vector<bool> fetched2(nbOfTuples,false);
11152 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11154 if(*seedElt>=0 && *seedElt<nbOfTuples)
11155 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11157 { 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()); }
11159 const int *arrInPtr=arrIn->getConstPointer();
11160 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11161 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11162 std::vector<int> idsToFetch1(seedBg,seedEnd);
11163 std::vector<int> idsToFetch2;
11164 std::vector<int> *idsToFetch=&idsToFetch1;
11165 std::vector<int> *idsToFetchOther=&idsToFetch2;
11166 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11168 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11169 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11171 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11172 std::swap(idsToFetch,idsToFetchOther);
11173 idsToFetchOther->clear();
11174 nbOfDepthPeelingPerformed++;
11176 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11179 int *retPtr=ret->getPointer();
11180 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11187 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11188 * 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
11189 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11190 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11192 * \param [in] start begin of set of ids of the input extraction (included)
11193 * \param [in] end end of set of ids of the input extraction (excluded)
11194 * \param [in] step step of the set of ids in range mode.
11195 * \param [in] arrIn arr origin array from which the extraction will be done.
11196 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11197 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11198 * \param [in] srcArrIndex index array of \b srcArr
11199 * \param [out] arrOut the resulting array
11200 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11202 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11204 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11205 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11206 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11208 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11209 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11212 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11214 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11215 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11216 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11218 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11220 if(it>=0 && it<nbOfTuples)
11221 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11224 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11225 throw INTERP_KERNEL::Exception(oss.str().c_str());
11228 srcArrIndexPtr=srcArrIndex->getConstPointer();
11229 arrIo->alloc(nbOfTuples+1,1);
11230 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11231 const int *arrInPtr=arrIn->getConstPointer();
11232 const int *srcArrPtr=srcArr->getConstPointer();
11233 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11234 int *arroPtr=arro->getPointer();
11235 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11237 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11240 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11241 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11245 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11246 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11249 arrOut=arro.retn();
11250 arrIndexOut=arrIo.retn();
11254 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11255 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11257 * \param [in] start begin of set of ids of the input extraction (included)
11258 * \param [in] end end of set of ids of the input extraction (excluded)
11259 * \param [in] step step of the set of ids in range mode.
11260 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11261 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11262 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11263 * \param [in] srcArrIndex index array of \b srcArr
11265 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11267 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11268 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11270 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11271 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11272 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11273 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11274 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11275 int *arrInOutPtr=arrInOut->getPointer();
11276 const int *srcArrPtr=srcArr->getConstPointer();
11277 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11279 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11281 if(it>=0 && it<nbOfTuples)
11283 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11284 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11287 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11288 throw INTERP_KERNEL::Exception(oss.str().c_str());
11293 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11294 throw INTERP_KERNEL::Exception(oss.str().c_str());
11300 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11301 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11302 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11303 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11304 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11306 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11308 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11310 checkFullyDefined();
11311 int mdim=getMeshDimension();
11312 int spaceDim=getSpaceDimension();
11314 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11315 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11316 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11317 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11318 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11319 ret->setCoords(getCoords());
11320 ret->allocateCells((int)partition.size());
11322 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11324 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11329 cell=tmp->buildUnionOf2DMesh();
11332 cell=tmp->buildUnionOf3DMesh();
11335 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11338 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11341 ret->finishInsertingCells();
11346 * This method partitions \b this into contiguous zone.
11347 * This method only needs a well defined connectivity. Coordinates are not considered here.
11348 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11350 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11352 int nbOfCellsCur=getNumberOfCells();
11353 std::vector<DataArrayInt *> ret;
11354 if(nbOfCellsCur<=0)
11356 DataArrayInt *neigh=0,*neighI=0;
11357 computeNeighborsOfCells(neigh,neighI);
11358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11359 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11360 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11362 while(seed<nbOfCellsCur)
11364 int nbOfPeelPerformed=0;
11365 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11366 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11368 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11369 ret.push_back((*it).retn());
11374 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11375 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11377 * \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.
11378 * \return a newly allocated DataArrayInt to be managed by the caller.
11379 * \throw In case of \a code has not the right format (typically of size 3*n)
11381 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11384 std::size_t nb=code.size()/3;
11385 if(code.size()%3!=0)
11386 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11387 ret->alloc((int)nb,2);
11388 int *retPtr=ret->getPointer();
11389 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11391 retPtr[0]=code[3*i+2];
11392 retPtr[1]=code[3*i+2]+code[3*i+1];
11398 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11399 * All cells in \a this are expected to be linear 3D cells.
11400 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11401 * It leads to an increase to number of cells.
11402 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11403 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11404 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11406 * \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.
11407 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11408 * \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.
11409 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11410 * an id of old cell producing it. The caller is to delete this array using
11411 * decrRef() as it is no more needed.
11412 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11414 * \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
11415 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11417 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11418 * \throw If \a this is not fully constituted with linear 3D cells.
11419 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11421 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11423 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11424 checkConnectivityFullyDefined();
11425 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11427 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11428 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11430 int *retPt(ret->getPointer());
11431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11432 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11433 const int *oldc(_nodal_connec->begin());
11434 const int *oldci(_nodal_connec_index->begin());
11435 const double *coords(_coords->begin());
11436 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11438 std::vector<int> a; std::vector<double> b;
11439 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11440 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11441 const int *aa(&a[0]);
11444 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11446 *it=(-(*(it))-1+nbNodes);
11447 addPts->insertAtTheEnd(b.begin(),b.end());
11448 nbNodes+=(int)b.size()/3;
11450 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11451 newConn->insertAtTheEnd(aa,aa+4);
11453 if(!addPts->empty())
11455 addPts->rearrange(3);
11456 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11457 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11458 ret0->setCoords(addPts);
11462 nbOfAdditionalPoints=0;
11463 ret0->setCoords(getCoords());
11465 ret0->setNodalConnectivity(newConn);
11467 ret->computeOffsets2();
11468 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11469 return ret0.retn();
11473 * 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).
11475 * \sa MEDCouplingUMesh::split2DCells
11477 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11479 checkConnectivityFullyDefined();
11480 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11481 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11482 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11483 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11484 int prevPosOfCi(ciPtr[0]);
11485 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11487 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11488 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11489 for(int j=0;j<sz;j++)
11491 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11492 for(int k=0;k<sz2;k++)
11493 *cPtr++=subPtr[offset2+k];
11495 *cPtr++=oldConn[prevPosOfCi+j+2];
11498 prevPosOfCi=ciPtr[1];
11499 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11502 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11503 _nodal_connec->decrRef();
11504 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11507 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11513 int ret(nodesCnter++);
11515 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11516 addCoo.insertAtTheEnd(newPt,newPt+2);
11521 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11527 int ret(nodesCnter++);
11529 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11530 addCoo.insertAtTheEnd(newPt,newPt+2);
11538 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)
11541 int trueStart(start>=0?start:nbOfEdges+start);
11542 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11543 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11548 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11549 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11550 middles.push_back(tmp3+offset);
11553 middles.push_back(connBg[trueStart+nbOfEdges]);
11557 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)
11559 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11560 newConnOfCell->pushBackSilent(tmpEnd);
11565 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11566 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11567 middles.push_back(tmp3+offset);
11570 middles.push_back(connBg[start+nbOfEdges]);
11574 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)
11576 // only the quadratic point to deal with:
11581 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11582 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11583 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11584 middles.push_back(tmp3+offset);
11587 middles.push_back(connBg[start+nbOfEdges]);
11594 * 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 ) .
11595 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11597 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11599 std::size_t sz(std::distance(connBg,connEnd));
11600 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11601 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11603 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11604 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11605 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11606 unsigned nbOfHit(0); // number of fusions operated
11607 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11608 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
11609 INTERP_KERNEL::NormalizedCellType typeOfSon;
11610 std::vector<int> middles;
11612 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11614 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11615 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11616 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11617 posEndElt = posBaseElt+1;
11619 // Look backward first: are the final edges of the cells colinear with the first ones?
11620 // This initializes posBaseElt.
11623 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11625 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11626 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11627 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11628 bool isColinear=eint->areColinears();
11641 // Now move forward:
11642 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11643 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11645 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11646 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11647 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11648 bool isColinear(eint->areColinears());
11660 //push [posBaseElt,posEndElt) in newConnOfCell using e
11661 // 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!
11663 // at the begining of the connectivity (insert type)
11664 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11665 else if((nbOfHit+nbOfTurn) != (nbs-1))
11667 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11668 if ((nbOfHit+nbOfTurn) == (nbs-1))
11669 // at the end (only quad points to deal with)
11670 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11671 posBaseElt=posEndElt;
11674 if(!middles.empty())
11675 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11680 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11682 * \return int - the number of new nodes created.
11683 * \sa MEDCouplingUMesh::split2DCells
11685 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11688 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11690 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11691 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11692 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11693 const double *oldCoordsPtr(getCoords()->begin());
11694 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11695 int prevPosOfCi(ciPtr[0]);
11696 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11698 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11699 for(int j=0;j<sz;j++)
11700 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11701 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11702 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11704 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11708 cPtr[1]=oldConn[prevPosOfCi+2+j];
11709 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11712 std::vector<INTERP_KERNEL::Node *> ns(3);
11713 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11714 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11715 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11716 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11717 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11719 cPtr[1]=subPtr[offset2+k];
11720 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11722 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11724 { cPtr[1]=tmpEnd; }
11725 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11727 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11728 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11731 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11732 _nodal_connec->decrRef();
11733 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11734 addCoo->rearrange(2);
11735 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11737 return addCoo->getNumberOfTuples();
11740 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11742 if(nodalConnec && nodalConnecIndex)
11745 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11746 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11748 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11749 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11753 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11754 _own_cell(true),_cell_id(-1),_nb_cell(0)
11759 _nb_cell=mesh->getNumberOfCells();
11763 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11771 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11772 _own_cell(false),_cell_id(bg-1),
11779 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11782 if(_cell_id<_nb_cell)
11791 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11797 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11799 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11802 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11808 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11816 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11822 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11827 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11832 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11834 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11837 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11842 _nb_cell=mesh->getNumberOfCells();
11846 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11853 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11855 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11856 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11857 if(_cell_id<_nb_cell)
11859 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11860 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11861 int startId=_cell_id;
11862 _cell_id+=nbOfElems;
11863 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11869 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11873 _conn=mesh->getNodalConnectivity()->getPointer();
11874 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11878 void MEDCouplingUMeshCell::next()
11880 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11885 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11888 std::string MEDCouplingUMeshCell::repr() const
11890 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11892 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11894 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11898 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11901 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11903 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11904 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11906 return INTERP_KERNEL::NORM_ERROR;
11909 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11912 if(_conn_lgth!=NOTICABLE_FIRST_VAL)