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. Closer is the estimation to the number of cells effectively inserted,
320 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
321 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
323 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
325 * \if ENABLE_EXAMPLES
326 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334 if(_nodal_connec_index)
336 _nodal_connec_index->decrRef();
340 _nodal_connec->decrRef();
342 _nodal_connec_index=DataArrayInt::New();
343 _nodal_connec_index->reserve(nbOfCells+1);
344 _nodal_connec_index->pushBackSilent(0);
345 _nodal_connec=DataArrayInt::New();
346 _nodal_connec->reserve(2*nbOfCells);
352 * Appends a cell to the connectivity array. For deeper understanding what is
353 * happening see \ref MEDCouplingUMeshNodalConnectivity.
354 * \param [in] type - type of cell to add.
355 * \param [in] size - number of nodes constituting this cell.
356 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
358 * \if ENABLE_EXAMPLES
359 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
365 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366 if(_nodal_connec_index==0)
367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368 if((int)cm.getDimension()==_mesh_dim)
371 if(size!=(int)cm.getNumberOfNodes())
373 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375 throw INTERP_KERNEL::Exception(oss.str().c_str());
377 int idx=_nodal_connec_index->back();
379 _nodal_connec_index->pushBackSilent(val);
380 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
385 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388 throw INTERP_KERNEL::Exception(oss.str().c_str());
393 * Compacts data arrays to release unused memory. This method is to be called after
394 * finishing cell insertion using \a this->insertNextCell().
396 * \if ENABLE_EXAMPLES
397 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
401 void MEDCouplingUMesh::finishInsertingCells()
403 _nodal_connec->pack();
404 _nodal_connec_index->pack();
405 _nodal_connec->declareAsNew();
406 _nodal_connec_index->declareAsNew();
411 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412 * Useful for python users.
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
416 return new MEDCouplingUMeshCellIterator(this);
420 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423 * Useful for python users.
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
427 if(!checkConsecutiveCellTypes())
428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429 return new MEDCouplingUMeshCellByTypeEntry(this);
433 * Returns a set of all cell types available in \a this mesh.
434 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435 * \warning this method does not throw any exception even if \a this is not defined.
436 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
444 * This method returns the sorted list of geometric types in \a this.
445 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
446 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
448 * \throw if connectivity in \a this is not correctly defined.
450 * \sa MEDCouplingMesh::getAllGeoTypes
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
454 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455 checkConnectivityFullyDefined();
456 int nbOfCells(getNumberOfCells());
459 if(getMeshLength()<1)
460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463 for(int i=1;i<nbOfCells;i++,ci++)
464 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
470 * This method is a method that compares \a this and \a other.
471 * This method compares \b all attributes, even names and component names.
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
476 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477 std::ostringstream oss; oss.precision(15);
478 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
481 reason="mesh given in input is not castable in MEDCouplingUMesh !";
484 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
486 if(_mesh_dim!=otherC->_mesh_dim)
488 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
492 if(_types!=otherC->_types)
494 oss << "umesh geometric type mismatch :\nThis geometric types are :";
495 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497 oss << "\nOther geometric types are :";
498 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
503 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504 if(_nodal_connec==0 || otherC->_nodal_connec==0)
506 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
509 if(_nodal_connec!=otherC->_nodal_connec)
510 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
512 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
515 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
518 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
521 if(_nodal_connec_index!=otherC->_nodal_connec_index)
522 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
524 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
531 * Checks if data arrays of this mesh (node coordinates, nodal
532 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
534 * \param [in] other - the mesh to compare with.
535 * \param [in] prec - precision value used to compare node coordinates.
536 * \return bool - \a true if the two meshes are same.
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
540 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
543 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
545 if(_mesh_dim!=otherC->_mesh_dim)
547 if(_types!=otherC->_types)
549 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550 if(_nodal_connec==0 || otherC->_nodal_connec==0)
552 if(_nodal_connec!=otherC->_nodal_connec)
553 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
555 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
558 if(_nodal_connec_index!=otherC->_nodal_connec_index)
559 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
565 * Checks if \a this and \a other meshes are geometrically equivalent with high
566 * probability, else an exception is thrown. The meshes are considered equivalent if
567 * (1) meshes contain the same number of nodes and the same number of elements of the
568 * same types (2) three cells of the two meshes (first, last and middle) are based
569 * on coincident nodes (with a specified precision).
570 * \param [in] other - the mesh to compare with.
571 * \param [in] prec - the precision used to compare nodes of the two meshes.
572 * \throw If the two meshes do not match.
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
576 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
583 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584 * cells each node belongs to.
585 * \warning For speed reasons, this method does not check if node ids in the nodal
586 * connectivity correspond to the size of node coordinates array.
587 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589 * dividing cell ids in \a revNodal into groups each referring to one
590 * node. Its every element (except the last one) is an index pointing to the
591 * first id of a group of cells. For example cells sharing the node #1 are
592 * described by following range of indices:
593 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595 * Number of cells sharing the *i*-th node is
596 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597 * \throw If the coordinates array is not set.
598 * \throw If the nodal connectivity of cells is not defined.
600 * \if ENABLE_EXAMPLES
601 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
608 int nbOfNodes=getNumberOfNodes();
609 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612 const int *conn=_nodal_connec->getConstPointer();
613 const int *connIndex=_nodal_connec_index->getConstPointer();
614 int nbOfCells=getNumberOfCells();
615 int nbOfEltsInRevNodal=0;
616 for(int eltId=0;eltId<nbOfCells;eltId++)
618 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621 if(*iter>=0)//for polyhedrons
623 nbOfEltsInRevNodal++;
624 revNodalIndxPtr[(*iter)+1]++;
627 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631 for(int eltId=0;eltId<nbOfCells;eltId++)
633 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636 if(*iter>=0)//for polyhedrons
637 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
654 if(cm.getOrientationStatus(nb,conn1,conn2))
661 class MinusOneSonsGenerator
664 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667 static const int DELTA=1;
669 const INTERP_KERNEL::CellModel& _cm;
672 class MinusOneSonsGeneratorBiQuadratic
675 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678 static const int DELTA=1;
680 const INTERP_KERNEL::CellModel& _cm;
683 class MinusTwoSonsGenerator
686 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689 static const int DELTA=2;
691 const INTERP_KERNEL::CellModel& _cm;
697 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699 * describing correspondence between cells of \a this and the result meshes are
700 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
701 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
703 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
704 * \warning For speed reasons, this method does not check if node ids in the nodal
705 * connectivity correspond to the size of node coordinates array.
706 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707 * to write this mesh to the MED file, its cells must be sorted using
708 * sortCellsInMEDFileFrmt().
709 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
710 * each cell of \a this mesh.
711 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712 * dividing cell ids in \a desc into groups each referring to one
713 * cell of \a this mesh. Its every element (except the last one) is an index
714 * pointing to the first id of a group of cells. For example cells of the
715 * result mesh bounding the cell #1 of \a this mesh are described by following
717 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722 * by each cell of the result mesh.
723 * \param [in,out] revDescIndx - the array, of length one more than number of cells
724 * in the result mesh,
725 * dividing cell ids in \a revDesc into groups each referring to one
726 * cell of the result mesh the same way as \a descIndx divides \a desc.
727 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728 * delete this mesh using decrRef() as it is no more needed.
729 * \throw If the coordinates array is not set.
730 * \throw If the nodal connectivity of cells is node defined.
731 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732 * revDescIndx == NULL.
734 * \if ENABLE_EXAMPLES
735 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
738 * \sa buildDescendingConnectivity2()
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
742 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
746 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750 * \sa MEDCouplingUMesh::buildDescendingConnectivity
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
755 if(getMeshDimension()!=3)
756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
761 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762 * this->getMeshDimension(), that bound cells of \a this mesh. In
763 * addition arrays describing correspondence between cells of \a this and the result
764 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
765 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766 * mesh. This method differs from buildDescendingConnectivity() in that apart
767 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768 * result meshes. So a positive id means that order of nodes in corresponding cells
769 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771 * i.e. cell ids are one-based.
772 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
773 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
774 * \warning For speed reasons, this method does not check if node ids in the nodal
775 * connectivity correspond to the size of node coordinates array.
776 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777 * to write this mesh to the MED file, its cells must be sorted using
778 * sortCellsInMEDFileFrmt().
779 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
780 * each cell of \a this mesh.
781 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782 * dividing cell ids in \a desc into groups each referring to one
783 * cell of \a this mesh. Its every element (except the last one) is an index
784 * pointing to the first id of a group of cells. For example cells of the
785 * result mesh bounding the cell #1 of \a this mesh are described by following
787 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792 * by each cell of the result mesh.
793 * \param [in,out] revDescIndx - the array, of length one more than number of cells
794 * in the result mesh,
795 * dividing cell ids in \a revDesc into groups each referring to one
796 * cell of the result mesh the same way as \a descIndx divides \a desc.
797 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798 * shares the node coordinates array with \a this mesh. The caller is to
799 * delete this mesh using decrRef() as it is no more needed.
800 * \throw If the coordinates array is not set.
801 * \throw If the nodal connectivity of cells is node defined.
802 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803 * revDescIndx == NULL.
805 * \if ENABLE_EXAMPLES
806 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
809 * \sa buildDescendingConnectivity()
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
813 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
817 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
819 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
820 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
822 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
823 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
824 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
826 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
832 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
834 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
838 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
839 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
840 * excluding a set of meshdim-1 cells in input descending connectivity.
841 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
842 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
843 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
845 * \param [in] desc descending connectivity array.
846 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
847 * \param [in] revDesc reverse descending connectivity array.
848 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
849 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
850 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
851 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
853 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
854 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
856 if(!desc || !descIndx || !revDesc || !revDescIndx)
857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
858 const int *descPtr=desc->getConstPointer();
859 const int *descIPtr=descIndx->getConstPointer();
860 const int *revDescPtr=revDesc->getConstPointer();
861 const int *revDescIPtr=revDescIndx->getConstPointer();
863 int nbCells=descIndx->getNumberOfTuples()-1;
864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
866 int *out1Ptr=out1->getPointer();
868 out0->reserve(desc->getNumberOfTuples());
869 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
871 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
873 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
875 out0->insertAtTheEnd(s.begin(),s.end());
877 *out1Ptr=out0->getNumberOfTuples();
879 neighbors=out0.retn();
880 neighborsIndx=out1.retn();
884 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
885 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
886 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
887 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
889 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
890 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
891 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
893 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
896 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
898 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
903 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
908 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
913 mesh1D=const_cast<MEDCouplingUMesh *>(this);
919 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
922 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
923 mesh1D->getReverseNodalConnectivity(desc,descIndx);
924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
925 ret0->alloc(desc->getNumberOfTuples(),1);
926 int *r0Pt(ret0->getPointer());
927 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
928 for(int i=0;i<nbNodes;i++,rni++)
930 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
931 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
933 neighbors=ret0.retn();
934 neighborsIdx=descIndx.retn();
940 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
941 * For speed reasons no check of this will be done.
943 template<class SonsGenerator>
944 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
946 if(!desc || !descIndx || !revDesc || !revDescIndx)
947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
948 checkConnectivityFullyDefined();
949 int nbOfCells=getNumberOfCells();
950 int nbOfNodes=getNumberOfNodes();
951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
952 int *revNodalIndxPtr=revNodalIndx->getPointer();
953 const int *conn=_nodal_connec->getConstPointer();
954 const int *connIndex=_nodal_connec_index->getConstPointer();
955 std::string name="Mesh constituent of "; name+=getName();
956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
957 ret->setCoords(getCoords());
958 ret->allocateCells(2*nbOfCells);
959 descIndx->alloc(nbOfCells+1,1);
960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
961 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
962 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
964 int pos=connIndex[eltId];
965 int posP1=connIndex[eltId+1];
966 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
967 SonsGenerator sg(cm);
968 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
969 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
970 for(unsigned i=0;i<nbOfSons;i++)
972 INTERP_KERNEL::NormalizedCellType cmsId;
973 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
974 for(unsigned k=0;k<nbOfNodesSon;k++)
976 revNodalIndxPtr[tmp[k]+1]++;
977 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
978 revDesc2->pushBackSilent(eltId);
980 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
982 int nbOfCellsM1=ret->getNumberOfCells();
983 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
985 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
986 int *revNodalPtr=revNodal->getPointer();
987 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
988 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
989 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
991 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
992 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
993 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
994 if(*iter>=0)//for polyhedrons
995 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
998 DataArrayInt *commonCells=0,*commonCellsI=0;
999 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1001 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1002 int newNbOfCellsM1=-1;
1003 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1004 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1005 std::vector<bool> isImpacted(nbOfCellsM1,false);
1006 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1007 for(int work2=work[0];work2!=work[1];work2++)
1008 isImpacted[commonCellsPtr[work2]]=true;
1009 const int *o2nM1Ptr=o2nM1->getConstPointer();
1010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1011 const int *n2oM1Ptr=n2oM1->getConstPointer();
1012 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1013 ret2->copyTinyInfoFrom(this);
1014 desc->alloc(descIndx->back(),1);
1015 int *descPtr=desc->getPointer();
1016 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1017 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1020 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1023 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1025 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1026 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1029 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1032 revDesc->reserve(newNbOfCellsM1);
1033 revDescIndx->alloc(newNbOfCellsM1+1,1);
1034 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1035 const int *revDesc2Ptr=revDesc2->getConstPointer();
1036 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1038 int oldCellIdM1=n2oM1Ptr[i];
1039 if(!isImpacted[oldCellIdM1])
1041 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1042 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1046 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1047 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1048 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1056 struct MEDCouplingAccVisit
1058 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1059 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1060 int _new_nb_of_nodes;
1066 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1067 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1068 * array of cell ids. Pay attention that after conversion all algorithms work slower
1069 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1070 * conversion due presence of invalid ids in the array of cells to convert, as a
1071 * result \a this mesh contains some already converted elements. In this case the 2D
1072 * mesh remains valid but 3D mesh becomes \b inconsistent!
1073 * \warning This method can significantly modify the order of geometric types in \a this,
1074 * hence, to write this mesh to the MED file, its cells must be sorted using
1075 * sortCellsInMEDFileFrmt().
1076 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1077 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1078 * cellIdsToConvertBg.
1079 * \throw If the coordinates array is not set.
1080 * \throw If the nodal connectivity of cells is node defined.
1081 * \throw If dimension of \a this mesh is not either 2 or 3.
1083 * \if ENABLE_EXAMPLES
1084 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1085 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1088 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1090 checkFullyDefined();
1091 int dim=getMeshDimension();
1093 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1094 int nbOfCells(getNumberOfCells());
1097 const int *connIndex=_nodal_connec_index->getConstPointer();
1098 int *conn=_nodal_connec->getPointer();
1099 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1101 if(*iter>=0 && *iter<nbOfCells)
1103 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1104 if(!cm.isQuadratic())
1105 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1107 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1111 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1112 oss << " in range [0," << nbOfCells << ") !";
1113 throw INTERP_KERNEL::Exception(oss.str().c_str());
1119 int *connIndex(_nodal_connec_index->getPointer());
1120 const int *connOld(_nodal_connec->getConstPointer());
1121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1122 std::vector<bool> toBeDone(nbOfCells,false);
1123 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1125 if(*iter>=0 && *iter<nbOfCells)
1126 toBeDone[*iter]=true;
1129 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130 oss << " in range [0," << nbOfCells << ") !";
1131 throw INTERP_KERNEL::Exception(oss.str().c_str());
1134 for(int cellId=0;cellId<nbOfCells;cellId++)
1136 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1137 int lgthOld(posP1-pos-1);
1138 if(toBeDone[cellId])
1140 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1141 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1142 int *tmp(new int[nbOfFaces*lgthOld+1]);
1143 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1144 for(unsigned j=0;j<nbOfFaces;j++)
1146 INTERP_KERNEL::NormalizedCellType type;
1147 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1151 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1152 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1153 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1158 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1159 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1162 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1168 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1169 * polyhedrons (if \a this is a 3D mesh).
1170 * \warning As this method is purely for user-friendliness and no optimization is
1171 * done to avoid construction of a useless vector, this method can be costly
1173 * \throw If the coordinates array is not set.
1174 * \throw If the nodal connectivity of cells is node defined.
1175 * \throw If dimension of \a this mesh is not either 2 or 3.
1177 void MEDCouplingUMesh::convertAllToPoly()
1179 int nbOfCells=getNumberOfCells();
1180 std::vector<int> cellIds(nbOfCells);
1181 for(int i=0;i<nbOfCells;i++)
1183 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1187 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1188 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1189 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1190 * base facet of the volume and the second half of nodes describes an opposite facet
1191 * having the same number of nodes as the base one. This method converts such
1192 * connectivity to a valid polyhedral format where connectivity of each facet is
1193 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1194 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1195 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1196 * a correct orientation of the first facet of a polyhedron, else orientation of a
1197 * corrected cell is reverse.<br>
1198 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1199 * it releases the user from boring description of polyhedra connectivity in the valid
1201 * \throw If \a this->getMeshDimension() != 3.
1202 * \throw If \a this->getSpaceDimension() != 3.
1203 * \throw If the nodal connectivity of cells is not defined.
1204 * \throw If the coordinates array is not set.
1205 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1206 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1208 * \if ENABLE_EXAMPLES
1209 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1210 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1213 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1215 checkFullyDefined();
1216 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1218 int nbOfCells=getNumberOfCells();
1219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1220 newCi->alloc(nbOfCells+1,1);
1221 int *newci=newCi->getPointer();
1222 const int *ci=_nodal_connec_index->getConstPointer();
1223 const int *c=_nodal_connec->getConstPointer();
1225 for(int i=0;i<nbOfCells;i++)
1227 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1228 if(type==INTERP_KERNEL::NORM_POLYHED)
1230 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1232 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1233 throw INTERP_KERNEL::Exception(oss.str().c_str());
1235 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1238 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1239 throw INTERP_KERNEL::Exception(oss.str().c_str());
1242 newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1245 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1248 newC->alloc(newci[nbOfCells],1);
1249 int *newc=newC->getPointer();
1250 for(int i=0;i<nbOfCells;i++)
1252 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1253 if(type==INTERP_KERNEL::NORM_POLYHED)
1255 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1256 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1258 for(std::size_t j=0;j<n1;j++)
1260 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1262 newc[n1+5*j+1]=c[ci[i]+1+j];
1263 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1264 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1265 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1270 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1272 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1273 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1278 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1279 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1280 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1281 * to write this mesh to the MED file, its cells must be sorted using
1282 * sortCellsInMEDFileFrmt().
1283 * \return \c true if at least one cell has been converted, \c false else. In the
1284 * last case the nodal connectivity remains unchanged.
1285 * \throw If the coordinates array is not set.
1286 * \throw If the nodal connectivity of cells is not defined.
1287 * \throw If \a this->getMeshDimension() < 0.
1289 bool MEDCouplingUMesh::unPolyze()
1291 checkFullyDefined();
1292 int mdim=getMeshDimension();
1294 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1297 int nbOfCells=getNumberOfCells();
1300 int initMeshLgth=getMeshLength();
1301 int *conn=_nodal_connec->getPointer();
1302 int *index=_nodal_connec_index->getPointer();
1307 for(int i=0;i<nbOfCells;i++)
1309 lgthOfCurCell=index[i+1]-posOfCurCell;
1310 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1311 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1312 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1316 switch(cm.getDimension())
1320 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1321 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1322 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1327 int nbOfFaces,lgthOfPolyhConn;
1328 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1329 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1334 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1338 ret=ret || (newType!=type);
1339 conn[newPos]=newType;
1341 posOfCurCell=index[i+1];
1346 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1347 newPos+=lgthOfCurCell;
1348 posOfCurCell+=lgthOfCurCell;
1352 if(newPos!=initMeshLgth)
1353 _nodal_connec->reAlloc(newPos);
1360 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1361 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1362 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1364 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal
1367 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1369 checkFullyDefined();
1370 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1372 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1373 coords->recenterForMaxPrecision(eps);
1375 int nbOfCells=getNumberOfCells();
1376 const int *conn=_nodal_connec->getConstPointer();
1377 const int *index=_nodal_connec_index->getConstPointer();
1378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1379 connINew->alloc(nbOfCells+1,1);
1380 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1383 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1385 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1387 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1391 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1392 *connINewPtr=connNew->getNumberOfTuples();
1395 setConnectivity(connNew,connINew,false);
1399 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1400 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1401 * the format of returned DataArrayInt instance.
1403 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1404 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1406 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1408 checkConnectivityFullyDefined();
1409 int nbOfCells=getNumberOfCells();
1410 const int *connIndex=_nodal_connec_index->getConstPointer();
1411 const int *conn=_nodal_connec->getConstPointer();
1412 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1413 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1414 std::vector<bool> retS(maxElt,false);
1415 for(int i=0;i<nbOfCells;i++)
1416 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1420 for(int i=0;i<maxElt;i++)
1423 DataArrayInt *ret=DataArrayInt::New();
1425 int *retPtr=ret->getPointer();
1426 for(int i=0;i<maxElt;i++)
1433 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1434 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1436 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1438 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1439 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1440 for(int i=0;i<nbOfCells;i++)
1441 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1444 if(conn[j]<nbOfNodes)
1445 nodeIdsInUse[conn[j]]=true;
1448 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1449 throw INTERP_KERNEL::Exception(oss.str().c_str());
1455 * Finds nodes not used in any cell and returns an array giving a new id to every node
1456 * by excluding the unused nodes, for which the array holds -1. The result array is
1457 * a mapping in "Old to New" mode.
1458 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1459 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1460 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1461 * if the node is unused or a new id else. The caller is to delete this
1462 * array using decrRef() as it is no more needed.
1463 * \throw If the coordinates array is not set.
1464 * \throw If the nodal connectivity of cells is not defined.
1465 * \throw If the nodal connectivity includes an invalid id.
1467 * \if ENABLE_EXAMPLES
1468 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1469 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1471 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1473 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1476 int nbOfNodes(getNumberOfNodes());
1477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1478 ret->alloc(nbOfNodes,1);
1479 int *traducer=ret->getPointer();
1480 std::fill(traducer,traducer+nbOfNodes,-1);
1481 int nbOfCells=getNumberOfCells();
1482 const int *connIndex=_nodal_connec_index->getConstPointer();
1483 const int *conn=_nodal_connec->getConstPointer();
1484 for(int i=0;i<nbOfCells;i++)
1485 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1488 if(conn[j]<nbOfNodes)
1489 traducer[conn[j]]=1;
1492 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1493 throw INTERP_KERNEL::Exception(oss.str().c_str());
1496 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1497 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1502 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1503 * For each cell in \b this the number of nodes constituting cell is computed.
1504 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1505 * So for pohyhedrons some nodes can be counted several times in the returned result.
1507 * \return a newly allocated array
1508 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1510 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1512 checkConnectivityFullyDefined();
1513 int nbOfCells=getNumberOfCells();
1514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1515 ret->alloc(nbOfCells,1);
1516 int *retPtr=ret->getPointer();
1517 const int *conn=getNodalConnectivity()->getConstPointer();
1518 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1519 for(int i=0;i<nbOfCells;i++,retPtr++)
1521 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1522 *retPtr=connI[i+1]-connI[i]-1;
1524 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1530 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1531 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1533 * \return DataArrayInt * - new object to be deallocated by the caller.
1534 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1536 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1538 checkConnectivityFullyDefined();
1539 int nbOfCells=getNumberOfCells();
1540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1541 ret->alloc(nbOfCells,1);
1542 int *retPtr=ret->getPointer();
1543 const int *conn=getNodalConnectivity()->getConstPointer();
1544 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1545 for(int i=0;i<nbOfCells;i++,retPtr++)
1547 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1548 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1549 *retPtr=(int)s.size();
1553 *retPtr=(int)s.size();
1560 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1561 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1563 * \return a newly allocated array
1565 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1567 checkConnectivityFullyDefined();
1568 int nbOfCells=getNumberOfCells();
1569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1570 ret->alloc(nbOfCells,1);
1571 int *retPtr=ret->getPointer();
1572 const int *conn=getNodalConnectivity()->getConstPointer();
1573 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1574 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1576 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1577 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1583 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1584 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1585 * array mean that the corresponding old node is no more used.
1586 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1587 * this->getNumberOfNodes() before call of this method. The caller is to
1588 * delete this array using decrRef() as it is no more needed.
1589 * \throw If the coordinates array is not set.
1590 * \throw If the nodal connectivity of cells is not defined.
1591 * \throw If the nodal connectivity includes an invalid id.
1592 * \sa areAllNodesFetched
1594 * \if ENABLE_EXAMPLES
1595 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1596 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1599 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1601 return MEDCouplingPointSet::zipCoordsTraducer();
1605 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1606 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1608 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1613 return AreCellsEqual0(conn,connI,cell1,cell2);
1615 return AreCellsEqual1(conn,connI,cell1,cell2);
1617 return AreCellsEqual2(conn,connI,cell1,cell2);
1619 return AreCellsEqual3(conn,connI,cell1,cell2);
1621 return AreCellsEqual7(conn,connI,cell1,cell2);
1623 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1627 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1629 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1631 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1637 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1639 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1641 int sz=connI[cell1+1]-connI[cell1];
1642 if(sz==connI[cell2+1]-connI[cell2])
1644 if(conn[connI[cell1]]==conn[connI[cell2]])
1646 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1647 unsigned dim=cm.getDimension();
1653 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1654 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1655 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1656 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1657 return work!=tmp+sz1?1:0;
1660 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1663 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1670 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1672 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1674 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1676 if(conn[connI[cell1]]==conn[connI[cell2]])
1678 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1679 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1687 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1689 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1691 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1693 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1701 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1703 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1705 int sz=connI[cell1+1]-connI[cell1];
1706 if(sz==connI[cell2+1]-connI[cell2])
1708 if(conn[connI[cell1]]==conn[connI[cell2]])
1710 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1711 unsigned dim=cm.getDimension();
1717 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1718 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1719 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1720 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1725 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1726 std::reverse_iterator<int *> it2((int *)tmp);
1727 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1733 return work!=tmp+sz1?1:0;
1736 {//case of SEG2 and SEG3
1737 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1739 if(!cm.isQuadratic())
1741 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1742 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1743 if(std::equal(it1,it2,conn+connI[cell2]+1))
1749 if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1763 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1764 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1765 * and result remains unchanged.
1766 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1767 * If in 'candidates' pool -1 value is considered as an empty value.
1768 * WARNING this method returns only ONE set of result !
1770 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1772 if(candidates.size()<1)
1775 std::vector<int>::const_iterator iter=candidates.begin();
1776 int start=(*iter++);
1777 for(;iter!=candidates.end();iter++)
1779 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1784 result->pushBackSilent(start);
1788 result->pushBackSilent(*iter);
1790 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1797 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1798 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1800 * \param [in] compType input specifying the technique used to compare cells each other.
1801 * - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1802 * - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1803 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1804 * - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1805 * can be used for users not sensitive to orientation of cell
1806 * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1807 * \param [out] commonCells
1808 * \param [out] commonCellsI
1809 * \return the correspondance array old to new in a newly allocated array.
1812 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1815 getReverseNodalConnectivity(revNodal,revNodalI);
1816 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1819 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1820 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1823 int nbOfCells=nodalI->getNumberOfTuples()-1;
1824 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1825 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1826 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1827 std::vector<bool> isFetched(nbOfCells,false);
1830 for(int i=0;i<nbOfCells;i++)
1834 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1835 std::vector<int> v,v2;
1836 if(connOfNode!=connPtr+connIPtr[i+1])
1838 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1839 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1842 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1846 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1847 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1848 v2.resize(std::distance(v2.begin(),it));
1852 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1854 int pos=commonCellsI->back();
1855 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1856 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1857 isFetched[*it]=true;
1865 for(int i=startCellId;i<nbOfCells;i++)
1869 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1870 std::vector<int> v,v2;
1871 if(connOfNode!=connPtr+connIPtr[i+1])
1873 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1876 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1880 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1881 v2.resize(std::distance(v2.begin(),it));
1885 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1887 int pos=commonCellsI->back();
1888 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1889 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1890 isFetched[*it]=true;
1896 commonCellsArr=commonCells.retn();
1897 commonCellsIArr=commonCellsI.retn();
1901 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1902 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1903 * than \a other->getNumberOfCells() in the returned array means that there is no
1904 * corresponding cell in \a this mesh.
1905 * It is expected that \a this and \a other meshes share the same node coordinates
1906 * array, if it is not so an exception is thrown.
1907 * \param [in] other - the mesh to compare with.
1908 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1909 * valid values [0,1,2], see zipConnectivityTraducer().
1910 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1911 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1912 * values. The caller is to delete this array using
1913 * decrRef() as it is no more needed.
1914 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1917 * \if ENABLE_EXAMPLES
1918 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1919 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1921 * \sa checkDeepEquivalOnSameNodesWith()
1922 * \sa checkGeoEquivalWith()
1924 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1926 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1927 int nbOfCells=getNumberOfCells();
1928 static const int possibleCompType[]={0,1,2};
1929 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1931 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1932 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1934 throw INTERP_KERNEL::Exception(oss.str().c_str());
1936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1937 arr=o2n->substr(nbOfCells);
1938 arr->setName(other->getName());
1940 if(other->getNumberOfCells()==0)
1942 return arr->getMaxValue(tmp)<nbOfCells;
1946 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1947 * This method tries to determine if \b other is fully included in \b this.
1948 * The main difference is that this method is not expected to throw exception.
1949 * This method has two outputs :
1951 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1952 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1954 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1957 DataArrayInt *commonCells=0,*commonCellsI=0;
1958 int thisNbCells=getNumberOfCells();
1959 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1961 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1962 int otherNbCells=other->getNumberOfCells();
1963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1964 arr2->alloc(otherNbCells,1);
1965 arr2->fillWithZero();
1966 int *arr2Ptr=arr2->getPointer();
1967 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1968 for(int i=0;i<nbOfCommon;i++)
1970 int start=commonCellsPtr[commonCellsIPtr[i]];
1971 if(start<thisNbCells)
1973 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1975 int sig=commonCellsPtr[j]>0?1:-1;
1976 int val=std::abs(commonCellsPtr[j])-1;
1977 if(val>=thisNbCells)
1978 arr2Ptr[val-thisNbCells]=sig*(start+1);
1982 arr2->setName(other->getName());
1983 if(arr2->presenceOfValue(0))
1989 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1992 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1993 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1995 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1996 std::vector<const MEDCouplingUMesh *> ms(2);
1999 return MergeUMeshesOnSameCoords(ms);
2003 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2004 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2005 * cellIds is not given explicitely but by a range python like.
2007 * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2008 * \return a newly allocated
2010 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2011 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2013 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2015 if(getMeshDimension()!=-1)
2016 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2019 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2021 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2023 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2025 return const_cast<MEDCouplingUMesh *>(this);
2030 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2031 * The result mesh shares or not the node coordinates array with \a this mesh depending
2032 * on \a keepCoords parameter.
2033 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2034 * to write this mesh to the MED file, its cells must be sorted using
2035 * sortCellsInMEDFileFrmt().
2036 * \param [in] begin - an array of cell ids to include to the new mesh.
2037 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2038 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2039 * array of \a this mesh, else "free" nodes are removed from the result mesh
2040 * by calling zipCoords().
2041 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2042 * to delete this mesh using decrRef() as it is no more needed.
2043 * \throw If the coordinates array is not set.
2044 * \throw If the nodal connectivity of cells is not defined.
2045 * \throw If any cell id in the array \a begin is not valid.
2047 * \if ENABLE_EXAMPLES
2048 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2049 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2052 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2054 if(getMeshDimension()!=-1)
2055 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2059 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2061 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2063 return const_cast<MEDCouplingUMesh *>(this);
2068 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2070 * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis.
2071 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2072 * The number of cells of \b this will remain the same with this method.
2074 * \param [in] begin begin of cell ids (included) of cells in this to assign
2075 * \param [in] end end of cell ids (excluded) of cells in this to assign
2076 * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ).
2077 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2079 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2081 checkConnectivityFullyDefined();
2082 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2083 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2084 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2085 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2087 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2088 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2089 throw INTERP_KERNEL::Exception(oss.str().c_str());
2091 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2092 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2094 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2095 throw INTERP_KERNEL::Exception(oss.str().c_str());
2097 int nbOfCells=getNumberOfCells();
2098 bool easyAssign=true;
2099 const int *connI=_nodal_connec_index->getConstPointer();
2100 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2101 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2103 if(*it>=0 && *it<nbOfCells)
2105 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2109 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2110 throw INTERP_KERNEL::Exception(oss.str().c_str());
2115 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2120 DataArrayInt *arrOut=0,*arrIOut=0;
2121 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2124 setConnectivity(arrOut,arrIOut,true);
2128 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2130 checkConnectivityFullyDefined();
2131 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2132 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2133 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2134 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2136 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2137 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2138 throw INTERP_KERNEL::Exception(oss.str().c_str());
2140 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2141 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2143 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2144 throw INTERP_KERNEL::Exception(oss.str().c_str());
2146 int nbOfCells=getNumberOfCells();
2147 bool easyAssign=true;
2148 const int *connI=_nodal_connec_index->getConstPointer();
2149 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2151 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2153 if(it>=0 && it<nbOfCells)
2155 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2159 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2160 throw INTERP_KERNEL::Exception(oss.str().c_str());
2165 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2170 DataArrayInt *arrOut=0,*arrIOut=0;
2171 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2174 setConnectivity(arrOut,arrIOut,true);
2179 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2180 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2181 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2182 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2184 * \param [in] begin input start of array of node ids.
2185 * \param [in] end input end of array of node ids.
2186 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2187 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2189 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2191 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2192 checkConnectivityFullyDefined();
2194 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2195 std::vector<bool> fastFinder(sz,false);
2196 for(const int *work=begin;work!=end;work++)
2197 if(*work>=0 && *work<sz)
2198 fastFinder[*work]=true;
2199 int nbOfCells=getNumberOfCells();
2200 const int *conn=getNodalConnectivity()->getConstPointer();
2201 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2202 for(int i=0;i<nbOfCells;i++)
2204 int ref=0,nbOfHit=0;
2205 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2209 if(fastFinder[*work2])
2212 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2213 cellIdsKept->pushBackSilent(i);
2215 cellIdsKeptArr=cellIdsKept.retn();
2219 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2220 * this->getMeshDimension(), that bound some cells of \a this mesh.
2221 * The cells of lower dimension to include to the result mesh are selected basing on
2222 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2223 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2224 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2225 * created mesh shares the node coordinates array with \a this mesh.
2226 * \param [in] begin - the array of node ids.
2227 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2228 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2229 * array \a begin are added, else cells whose any node is in the
2230 * array \a begin are added.
2231 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2232 * to delete this mesh using decrRef() as it is no more needed.
2233 * \throw If the coordinates array is not set.
2234 * \throw If the nodal connectivity of cells is not defined.
2235 * \throw If any node id in \a begin is not valid.
2237 * \if ENABLE_EXAMPLES
2238 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2239 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2242 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2245 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2246 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2247 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2248 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2252 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2253 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2254 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2255 * array of \a this mesh, else "free" nodes are removed from the result mesh
2256 * by calling zipCoords().
2257 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2258 * to delete this mesh using decrRef() as it is no more needed.
2259 * \throw If the coordinates array is not set.
2260 * \throw If the nodal connectivity of cells is not defined.
2262 * \if ENABLE_EXAMPLES
2263 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2264 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2267 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2269 DataArrayInt *desc=DataArrayInt::New();
2270 DataArrayInt *descIndx=DataArrayInt::New();
2271 DataArrayInt *revDesc=DataArrayInt::New();
2272 DataArrayInt *revDescIndx=DataArrayInt::New();
2274 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2277 descIndx->decrRef();
2278 int nbOfCells=meshDM1->getNumberOfCells();
2279 const int *revDescIndxC=revDescIndx->getConstPointer();
2280 std::vector<int> boundaryCells;
2281 for(int i=0;i<nbOfCells;i++)
2282 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2283 boundaryCells.push_back(i);
2284 revDescIndx->decrRef();
2285 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2290 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2291 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2292 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2294 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2296 checkFullyDefined();
2297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2302 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2303 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2307 const int *revDescPtr=revDesc->getConstPointer();
2308 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2309 int nbOfCells=getNumberOfCells();
2310 std::vector<bool> ret1(nbOfCells,false);
2312 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2313 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2314 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2316 DataArrayInt *ret2=DataArrayInt::New();
2318 int *ret2Ptr=ret2->getPointer();
2320 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2323 ret2->setName("BoundaryCells");
2328 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2329 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2330 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2331 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2333 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2334 * This method method returns cells ids set s = s1 + s2 where :
2336 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2337 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2339 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2342 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2343 * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2344 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2346 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2348 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2349 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2350 checkConnectivityFullyDefined();
2351 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2352 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2358 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2359 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2360 DataArrayInt *idsOtherInConsti=0;
2361 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2364 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2366 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2367 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2370 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2371 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2373 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2374 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2375 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2376 neighThisPartAuto=0;
2377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2378 const int li[2]={0,1};
2379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2380 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2384 cellIdsRk0=s0arr.retn();
2385 cellIdsRk1=s_renum1.retn();
2389 * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2390 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2392 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2394 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2397 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2402 revDesc=0; desc=0; descIndx=0;
2403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2405 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2409 * Finds nodes lying on the boundary of \a this mesh.
2410 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2411 * nodes. The caller is to delete this array using decrRef() as it is no
2413 * \throw If the coordinates array is not set.
2414 * \throw If the nodal connectivity of cells is node defined.
2416 * \if ENABLE_EXAMPLES
2417 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2418 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2421 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2423 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2424 return skin->computeFetchedNodeIds();
2427 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2430 return const_cast<MEDCouplingUMesh *>(this);
2434 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2435 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2436 * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2437 * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2438 * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2440 * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2441 * parameter is altered during the call.
2442 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2443 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2444 * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2446 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2448 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2449 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2451 checkFullyDefined();
2452 otherDimM1OnSameCoords.checkFullyDefined();
2453 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2455 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2456 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2457 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2458 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2461 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2462 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2466 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2468 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2470 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2471 DataArrayInt *idsTmp=0;
2472 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2475 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2476 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2477 DataArrayInt *tmp0=0,*tmp1=0;
2478 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2481 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2482 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2483 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2484 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2486 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2487 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2488 nodeIdsToDuplicate=s3.retn();
2492 * This method operates a modification of the connectivity and coords in \b this.
2493 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2494 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2495 * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2496 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2497 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2499 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2501 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2502 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2504 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2506 int nbOfNodes=getNumberOfNodes();
2507 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2508 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2512 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2513 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2515 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2517 * \sa renumberNodesInConn
2519 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2521 checkConnectivityFullyDefined();
2522 int *conn(getNodalConnectivity()->getPointer());
2523 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2524 int nbOfCells(getNumberOfCells());
2525 for(int i=0;i<nbOfCells;i++)
2526 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2528 int& node=conn[iconn];
2529 if(node>=0)//avoid polyhedron separator
2534 _nodal_connec->declareAsNew();
2539 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2540 * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2543 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2545 checkConnectivityFullyDefined();
2546 int *conn(getNodalConnectivity()->getPointer());
2547 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2548 int nbOfCells(getNumberOfCells());
2549 for(int i=0;i<nbOfCells;i++)
2550 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2552 int& node=conn[iconn];
2553 if(node>=0)//avoid polyhedron separator
2555 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2556 if(it!=newNodeNumbersO2N.end())
2562 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2563 throw INTERP_KERNEL::Exception(oss.str().c_str());
2567 _nodal_connec->declareAsNew();
2572 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2573 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2574 * This method is a generalization of shiftNodeNumbersInConn().
2575 * \warning This method performs no check of validity of new ids. **Use it with care !**
2576 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2577 * this->getNumberOfNodes(), in "Old to New" mode.
2578 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2579 * \throw If the nodal connectivity of cells is not defined.
2581 * \if ENABLE_EXAMPLES
2582 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2583 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2586 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2588 checkConnectivityFullyDefined();
2589 int *conn=getNodalConnectivity()->getPointer();
2590 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2591 int nbOfCells(getNumberOfCells());
2592 for(int i=0;i<nbOfCells;i++)
2593 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2595 int& node=conn[iconn];
2596 if(node>=0)//avoid polyhedron separator
2598 node=newNodeNumbersO2N[node];
2601 _nodal_connec->declareAsNew();
2606 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2607 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2608 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2610 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2612 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2614 checkConnectivityFullyDefined();
2615 int *conn=getNodalConnectivity()->getPointer();
2616 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2617 int nbOfCells=getNumberOfCells();
2618 for(int i=0;i<nbOfCells;i++)
2619 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2621 int& node=conn[iconn];
2622 if(node>=0)//avoid polyhedron separator
2627 _nodal_connec->declareAsNew();
2632 * This method operates a modification of the connectivity in \b this.
2633 * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method.
2634 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2635 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2636 * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2637 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2638 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2640 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2641 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2643 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2644 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2645 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2647 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2649 checkConnectivityFullyDefined();
2650 std::map<int,int> m;
2652 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2654 int *conn=getNodalConnectivity()->getPointer();
2655 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2656 int nbOfCells=getNumberOfCells();
2657 for(int i=0;i<nbOfCells;i++)
2658 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2660 int& node=conn[iconn];
2661 if(node>=0)//avoid polyhedron separator
2663 std::map<int,int>::iterator it=m.find(node);
2672 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2674 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2675 * After the call of this method the number of cells remains the same as before.
2677 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2678 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2679 * be strictly in [0;this->getNumberOfCells()).
2681 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2682 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2683 * should be contained in[0;this->getNumberOfCells()).
2685 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2687 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2689 checkConnectivityFullyDefined();
2690 int nbCells=getNumberOfCells();
2691 const int *array=old2NewBg;
2693 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2695 const int *conn=_nodal_connec->getConstPointer();
2696 const int *connI=_nodal_connec_index->getConstPointer();
2697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2698 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2699 const int *n2oPtr=n2o->begin();
2700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2701 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2702 newConn->copyStringInfoFrom(*_nodal_connec);
2703 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2704 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2705 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2707 int *newC=newConn->getPointer();
2708 int *newCI=newConnI->getPointer();
2711 for(int i=0;i<nbCells;i++)
2714 int nbOfElts=connI[pos+1]-connI[pos];
2715 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2720 setConnectivity(newConn,newConnI);
2722 free(const_cast<int *>(array));
2726 * Finds cells whose bounding boxes intersect a given bounding box.
2727 * \param [in] bbox - an array defining the bounding box via coordinates of its
2728 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2730 * \param [in] eps - a factor used to increase size of the bounding box of cell
2731 * before comparing it with \a bbox. This factor is multiplied by the maximal
2732 * extent of the bounding box of cell to produce an addition to this bounding box.
2733 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2734 * cells. The caller is to delete this array using decrRef() as it is no more
2736 * \throw If the coordinates array is not set.
2737 * \throw If the nodal connectivity of cells is not defined.
2739 * \if ENABLE_EXAMPLES
2740 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2741 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2744 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2746 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2747 if(getMeshDimension()==-1)
2749 elems->pushBackSilent(0);
2750 return elems.retn();
2752 int dim=getSpaceDimension();
2753 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2754 const int* conn = getNodalConnectivity()->getConstPointer();
2755 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2756 const double* coords = getCoords()->getConstPointer();
2757 int nbOfCells=getNumberOfCells();
2758 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2760 for (int i=0; i<dim; i++)
2762 elem_bb[i*2]=std::numeric_limits<double>::max();
2763 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2766 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2768 int node= conn[inode];
2769 if(node>=0)//avoid polyhedron separator
2771 for (int idim=0; idim<dim; idim++)
2773 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2775 elem_bb[idim*2] = coords[node*dim+idim] ;
2777 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2779 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2784 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2785 elems->pushBackSilent(ielem);
2787 return elems.retn();
2791 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2792 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2793 * added in 'elems' parameter.
2795 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2798 if(getMeshDimension()==-1)
2800 elems->pushBackSilent(0);
2801 return elems.retn();
2803 int dim=getSpaceDimension();
2804 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2805 const int* conn = getNodalConnectivity()->getConstPointer();
2806 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2807 const double* coords = getCoords()->getConstPointer();
2808 int nbOfCells=getNumberOfCells();
2809 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2811 for (int i=0; i<dim; i++)
2813 elem_bb[i*2]=std::numeric_limits<double>::max();
2814 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2817 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2819 int node= conn[inode];
2820 if(node>=0)//avoid polyhedron separator
2822 for (int idim=0; idim<dim; idim++)
2824 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2826 elem_bb[idim*2] = coords[node*dim+idim] ;
2828 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2830 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2835 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2836 elems->pushBackSilent(ielem);
2838 return elems.retn();
2842 * Returns a type of a cell by its id.
2843 * \param [in] cellId - the id of the cell of interest.
2844 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2845 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2847 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2849 const int *ptI=_nodal_connec_index->getConstPointer();
2850 const int *pt=_nodal_connec->getConstPointer();
2851 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2852 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2855 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2856 throw INTERP_KERNEL::Exception(oss.str().c_str());
2861 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2862 * This method does not throw exception if geometric type \a type is not in \a this.
2863 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2864 * The coordinates array is not considered here.
2866 * \param [in] type the geometric type
2867 * \return cell ids in this having geometric type \a type.
2869 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2872 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2874 checkConnectivityFullyDefined();
2875 int nbCells=getNumberOfCells();
2876 int mdim=getMeshDimension();
2877 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2878 if(mdim!=(int)cm.getDimension())
2879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2880 const int *ptI=_nodal_connec_index->getConstPointer();
2881 const int *pt=_nodal_connec->getConstPointer();
2882 for(int i=0;i<nbCells;i++)
2884 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2885 ret->pushBackSilent(i);
2891 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2893 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2895 const int *ptI=_nodal_connec_index->getConstPointer();
2896 const int *pt=_nodal_connec->getConstPointer();
2897 int nbOfCells=getNumberOfCells();
2899 for(int i=0;i<nbOfCells;i++)
2900 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2906 * Returns the nodal connectivity of a given cell.
2907 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2908 * all returned node ids can be used in getCoordinatesOfNode().
2909 * \param [in] cellId - an id of the cell of interest.
2910 * \param [in,out] conn - a vector where the node ids are appended. It is not
2911 * cleared before the appending.
2912 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2914 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2916 const int *ptI=_nodal_connec_index->getConstPointer();
2917 const int *pt=_nodal_connec->getConstPointer();
2918 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2923 std::string MEDCouplingUMesh::simpleRepr() const
2925 static const char msg0[]="No coordinates specified !";
2926 std::ostringstream ret;
2927 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2928 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2930 double tt=getTime(tmpp1,tmpp2);
2931 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2932 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2934 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2936 { ret << " Mesh dimension has not been set or is invalid !"; }
2939 const int spaceDim=getSpaceDimension();
2940 ret << spaceDim << "\nInfo attached on space dimension : ";
2941 for(int i=0;i<spaceDim;i++)
2942 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2946 ret << msg0 << "\n";
2947 ret << "Number of nodes : ";
2949 ret << getNumberOfNodes() << "\n";
2951 ret << msg0 << "\n";
2952 ret << "Number of cells : ";
2953 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2954 ret << getNumberOfCells() << "\n";
2956 ret << "No connectivity specified !" << "\n";
2957 ret << "Cell types present : ";
2958 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2960 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2961 ret << cm.getRepr() << " ";
2967 std::string MEDCouplingUMesh::advancedRepr() const
2969 std::ostringstream ret;
2970 ret << simpleRepr();
2971 ret << "\nCoordinates array : \n___________________\n\n";
2973 _coords->reprWithoutNameStream(ret);
2975 ret << "No array set !\n";
2976 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2977 reprConnectivityOfThisLL(ret);
2982 * This method returns a C++ code that is a dump of \a this.
2983 * This method will throw if this is not fully defined.
2985 std::string MEDCouplingUMesh::cppRepr() const
2987 static const char coordsName[]="coords";
2988 static const char connName[]="conn";
2989 static const char connIName[]="connI";
2990 checkFullyDefined();
2991 std::ostringstream ret; ret << "// coordinates" << std::endl;
2992 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2993 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2994 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2995 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2996 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2997 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2998 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3002 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3004 std::ostringstream ret;
3005 reprConnectivityOfThisLL(ret);
3010 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3011 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3012 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3015 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3016 * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
3017 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3019 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3021 int mdim=getMeshDimension();
3023 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3024 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3026 bool needToCpyCT=true;
3029 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3037 if(!_nodal_connec_index)
3039 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3044 tmp2=_nodal_connec_index;
3047 ret->setConnectivity(tmp1,tmp2,false);
3052 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3053 ret->setCoords(coords);
3056 ret->setCoords(_coords);
3060 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3062 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3064 int nbOfCells=getNumberOfCells();
3065 const int *c=_nodal_connec->getConstPointer();
3066 const int *ci=_nodal_connec_index->getConstPointer();
3067 for(int i=0;i<nbOfCells;i++)
3069 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3070 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3071 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3076 stream << "Connectivity not defined !\n";
3079 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3081 const int *ptI=_nodal_connec_index->getConstPointer();
3082 const int *pt=_nodal_connec->getConstPointer();
3083 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3084 return ptI[cellId+1]-ptI[cellId]-1;
3086 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3090 * Returns types of cells of the specified part of \a this mesh.
3091 * This method avoids computing sub-mesh explicitely to get its types.
3092 * \param [in] begin - an array of cell ids of interest.
3093 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3094 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3095 * describing the cell types.
3096 * \throw If the coordinates array is not set.
3097 * \throw If the nodal connectivity of cells is not defined.
3098 * \sa getAllGeoTypes()
3100 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3102 checkFullyDefined();
3103 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3104 const int *conn=_nodal_connec->getConstPointer();
3105 const int *connIndex=_nodal_connec_index->getConstPointer();
3106 for(const int *w=begin;w!=end;w++)
3107 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3112 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3113 * a set of types of cells constituting \a this mesh.
3114 * This method is for advanced users having prepared their connectivity before. For
3115 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3116 * \param [in] conn - the nodal connectivity array.
3117 * \param [in] connIndex - the nodal connectivity index array.
3118 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3121 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3123 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3124 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3125 if(isComputingTypes)
3131 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3132 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3134 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3135 _nodal_connec(0),_nodal_connec_index(0),
3136 _types(other._types)
3138 if(other._nodal_connec)
3139 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3140 if(other._nodal_connec_index)
3141 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3144 MEDCouplingUMesh::~MEDCouplingUMesh()
3147 _nodal_connec->decrRef();
3148 if(_nodal_connec_index)
3149 _nodal_connec_index->decrRef();
3153 * Recomputes a set of cell types of \a this mesh. For more info see
3154 * \ref MEDCouplingUMeshNodalConnectivity.
3156 void MEDCouplingUMesh::computeTypes()
3158 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3162 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3164 void MEDCouplingUMesh::checkFullyDefined() const
3166 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3167 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3171 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3173 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3175 if(!_nodal_connec_index || !_nodal_connec)
3176 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3180 * Returns a number of cells constituting \a this mesh.
3181 * \return int - the number of cells in \a this mesh.
3182 * \throw If the nodal connectivity of cells is not defined.
3184 int MEDCouplingUMesh::getNumberOfCells() const
3186 if(_nodal_connec_index)
3187 return _nodal_connec_index->getNumberOfTuples()-1;
3192 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3196 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3197 * mesh. For more info see \ref MEDCouplingMeshesPage.
3198 * \return int - the dimension of \a this mesh.
3199 * \throw If the mesh dimension is not defined using setMeshDimension().
3201 int MEDCouplingUMesh::getMeshDimension() const
3204 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3209 * Returns a length of the nodal connectivity array.
3210 * This method is for test reason. Normally the integer returned is not useable by
3211 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3212 * \return int - the length of the nodal connectivity array.
3214 int MEDCouplingUMesh::getMeshLength() const
3216 return _nodal_connec->getNbOfElems();
3220 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3222 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3224 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3225 tinyInfo.push_back(getMeshDimension());
3226 tinyInfo.push_back(getNumberOfCells());
3228 tinyInfo.push_back(getMeshLength());
3230 tinyInfo.push_back(-1);
3234 * First step of unserialization process.
3236 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3238 return tinyInfo[6]<=0;
3242 * Second step of serialization process.
3243 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3245 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3247 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3249 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3253 * Third and final step of serialization process.
3255 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3257 MEDCouplingPointSet::serialize(a1,a2);
3258 if(getMeshDimension()>-1)
3260 a1=DataArrayInt::New();
3261 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3262 int *ptA1=a1->getPointer();
3263 const int *conn=getNodalConnectivity()->getConstPointer();
3264 const int *index=getNodalConnectivityIndex()->getConstPointer();
3265 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3266 std::copy(conn,conn+getMeshLength(),ptA1);
3273 * Second and final unserialization process.
3274 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3276 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3278 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3279 setMeshDimension(tinyInfo[5]);
3283 const int *recvBuffer=a1->getConstPointer();
3284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3285 myConnecIndex->alloc(tinyInfo[6]+1,1);
3286 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3288 myConnec->alloc(tinyInfo[7],1);
3289 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3290 setConnectivity(myConnec, myConnecIndex);
3295 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3296 * CellIds are given using range specified by a start an end and step.
3298 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3300 checkFullyDefined();
3301 int ncell=getNumberOfCells();
3302 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3303 ret->_mesh_dim=_mesh_dim;
3304 ret->setCoords(_coords);
3305 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3307 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3309 const int *conn=_nodal_connec->getConstPointer();
3310 const int *connIndex=_nodal_connec_index->getConstPointer();
3311 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3313 if(work>=0 && work<ncell)
3315 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3319 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3320 throw INTERP_KERNEL::Exception(oss.str().c_str());
3323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3324 int *newConnPtr=newConn->getPointer();
3325 std::set<INTERP_KERNEL::NormalizedCellType> types;
3327 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3329 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3330 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3332 ret->setConnectivity(newConn,newConnI,false);
3334 ret->copyTinyInfoFrom(this);
3339 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3340 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3341 * The return newly allocated mesh will share the same coordinates as \a this.
3343 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3345 checkConnectivityFullyDefined();
3346 int ncell=getNumberOfCells();
3347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3348 ret->_mesh_dim=_mesh_dim;
3349 ret->setCoords(_coords);
3350 std::size_t nbOfElemsRet=std::distance(begin,end);
3351 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3353 const int *conn=_nodal_connec->getConstPointer();
3354 const int *connIndex=_nodal_connec_index->getConstPointer();
3356 for(const int *work=begin;work!=end;work++,newNbring++)
3358 if(*work>=0 && *work<ncell)
3359 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3363 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3364 throw INTERP_KERNEL::Exception(oss.str().c_str());
3367 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3368 int *connRetWork=connRet;
3369 std::set<INTERP_KERNEL::NormalizedCellType> types;
3370 for(const int *work=begin;work!=end;work++)
3372 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3373 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3376 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3378 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3379 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3381 ret->copyTinyInfoFrom(this);
3386 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3388 * For 1D cells, the returned field contains lengths.<br>
3389 * For 2D cells, the returned field contains areas.<br>
3390 * For 3D cells, the returned field contains volumes.
3391 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3392 * orientation, i.e. the volume is always positive.
3393 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3394 * and one time . The caller is to delete this field using decrRef() as it is no
3397 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3399 std::string name="MeasureOfMesh_";
3401 int nbelem=getNumberOfCells();
3402 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3403 field->setName(name);
3404 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3405 array->alloc(nbelem,1);
3406 double *area_vol=array->getPointer();
3407 field->setArray(array) ; array=0;
3408 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3409 field->synchronizeTimeWithMesh();
3410 if(getMeshDimension()!=-1)
3413 INTERP_KERNEL::NormalizedCellType type;
3414 int dim_space=getSpaceDimension();
3415 const double *coords=getCoords()->getConstPointer();
3416 const int *connec=getNodalConnectivity()->getConstPointer();
3417 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3418 for(int iel=0;iel<nbelem;iel++)
3420 ipt=connec_index[iel];
3421 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3422 area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3425 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3429 area_vol[0]=std::numeric_limits<double>::max();
3431 return field.retn();
3435 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3437 * For 1D cells, the returned array contains lengths.<br>
3438 * For 2D cells, the returned array contains areas.<br>
3439 * For 3D cells, the returned array contains volumes.
3440 * This method avoids building explicitly a part of \a this mesh to perform the work.
3441 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3442 * orientation, i.e. the volume is always positive.
3443 * \param [in] begin - an array of cell ids of interest.
3444 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3445 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3446 * delete this array using decrRef() as it is no more needed.
3448 * \if ENABLE_EXAMPLES
3449 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3450 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3452 * \sa getMeasureField()
3454 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3456 std::string name="PartMeasureOfMesh_";
3458 int nbelem=(int)std::distance(begin,end);
3459 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3460 array->setName(name);
3461 array->alloc(nbelem,1);
3462 double *area_vol=array->getPointer();
3463 if(getMeshDimension()!=-1)
3466 INTERP_KERNEL::NormalizedCellType type;
3467 int dim_space=getSpaceDimension();
3468 const double *coords=getCoords()->getConstPointer();
3469 const int *connec=getNodalConnectivity()->getConstPointer();
3470 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3471 for(const int *iel=begin;iel!=end;iel++)
3473 ipt=connec_index[*iel];
3474 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3475 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3478 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3482 area_vol[0]=std::numeric_limits<double>::max();
3484 return array.retn();
3488 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3489 * \a this one. The returned field contains the dual cell volume for each corresponding
3490 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3491 * the dual mesh in P1 sens of \a this.<br>
3492 * For 1D cells, the returned field contains lengths.<br>
3493 * For 2D cells, the returned field contains areas.<br>
3494 * For 3D cells, the returned field contains volumes.
3495 * This method is useful to check "P1*" conservative interpolators.
3496 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3497 * orientation, i.e. the volume is always positive.
3498 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499 * nodes and one time. The caller is to delete this array using decrRef() as
3500 * it is no more needed.
3502 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3504 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3505 std::string name="MeasureOnNodeOfMesh_";
3507 int nbNodes=getNumberOfNodes();
3508 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3509 double cst=1./((double)getMeshDimension()+1.);
3510 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3511 array->alloc(nbNodes,1);
3512 double *valsToFill=array->getPointer();
3513 std::fill(valsToFill,valsToFill+nbNodes,0.);
3514 const double *values=tmp->getArray()->getConstPointer();
3515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3516 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3517 getReverseNodalConnectivity(da,daInd);
3518 const int *daPtr=da->getConstPointer();
3519 const int *daIPtr=daInd->getConstPointer();
3520 for(int i=0;i<nbNodes;i++)
3521 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3522 valsToFill[i]+=cst*values[*cell];
3524 ret->setArray(array);
3529 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3530 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3531 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3532 * and are normalized.
3533 * <br> \a this can be either
3534 * - a 2D mesh in 2D or 3D space or
3535 * - an 1D mesh in 2D space.
3537 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3538 * cells and one time. The caller is to delete this field using decrRef() as
3539 * it is no more needed.
3540 * \throw If the nodal connectivity of cells is not defined.
3541 * \throw If the coordinates array is not set.
3542 * \throw If the mesh dimension is not set.
3543 * \throw If the mesh and space dimension is not as specified above.
3545 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3547 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3548 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3549 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3550 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3551 int nbOfCells=getNumberOfCells();
3552 int nbComp=getMeshDimension()+1;
3553 array->alloc(nbOfCells,nbComp);
3554 double *vals=array->getPointer();
3555 const int *connI=_nodal_connec_index->getConstPointer();
3556 const int *conn=_nodal_connec->getConstPointer();
3557 const double *coords=_coords->getConstPointer();
3558 if(getMeshDimension()==2)
3560 if(getSpaceDimension()==3)
3562 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3563 const double *locPtr=loc->getConstPointer();
3564 for(int i=0;i<nbOfCells;i++,vals+=3)
3566 int offset=connI[i];
3567 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3568 double n=INTERP_KERNEL::norm<3>(vals);
3569 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3574 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3575 const double *isAbsPtr=isAbs->getArray()->begin();
3576 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3577 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3580 else//meshdimension==1
3583 for(int i=0;i<nbOfCells;i++)
3585 int offset=connI[i];
3586 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3587 double n=INTERP_KERNEL::norm<2>(tmp);
3588 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3593 ret->setArray(array);
3595 ret->synchronizeTimeWithSupport();
3600 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3601 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3602 * and are normalized.
3603 * <br> \a this can be either
3604 * - a 2D mesh in 2D or 3D space or
3605 * - an 1D mesh in 2D space.
3607 * This method avoids building explicitly a part of \a this mesh to perform the work.
3608 * \param [in] begin - an array of cell ids of interest.
3609 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3610 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3611 * cells and one time. The caller is to delete this field using decrRef() as
3612 * it is no more needed.
3613 * \throw If the nodal connectivity of cells is not defined.
3614 * \throw If the coordinates array is not set.
3615 * \throw If the mesh dimension is not set.
3616 * \throw If the mesh and space dimension is not as specified above.
3617 * \sa buildOrthogonalField()
3619 * \if ENABLE_EXAMPLES
3620 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3621 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3624 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3626 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3627 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3628 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3629 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3630 std::size_t nbelems=std::distance(begin,end);
3631 int nbComp=getMeshDimension()+1;
3632 array->alloc((int)nbelems,nbComp);
3633 double *vals=array->getPointer();
3634 const int *connI=_nodal_connec_index->getConstPointer();
3635 const int *conn=_nodal_connec->getConstPointer();
3636 const double *coords=_coords->getConstPointer();
3637 if(getMeshDimension()==2)
3639 if(getSpaceDimension()==3)
3641 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3642 const double *locPtr=loc->getConstPointer();
3643 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3645 int offset=connI[*i];
3646 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3647 double n=INTERP_KERNEL::norm<3>(vals);
3648 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3653 for(std::size_t i=0;i<nbelems;i++)
3654 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3657 else//meshdimension==1
3660 for(const int *i=begin;i!=end;i++)
3662 int offset=connI[*i];
3663 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3664 double n=INTERP_KERNEL::norm<2>(tmp);
3665 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3670 ret->setArray(array);
3672 ret->synchronizeTimeWithSupport();
3677 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3678 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3679 * and are \b not normalized.
3680 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3681 * cells and one time. The caller is to delete this field using decrRef() as
3682 * it is no more needed.
3683 * \throw If the nodal connectivity of cells is not defined.
3684 * \throw If the coordinates array is not set.
3685 * \throw If \a this->getMeshDimension() != 1.
3686 * \throw If \a this mesh includes cells of type other than SEG2.
3688 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3690 if(getMeshDimension()!=1)
3691 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3692 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3693 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3694 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3695 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3696 int nbOfCells=getNumberOfCells();
3697 int spaceDim=getSpaceDimension();
3698 array->alloc(nbOfCells,spaceDim);
3699 double *pt=array->getPointer();
3700 const double *coo=getCoords()->getConstPointer();
3701 std::vector<int> conn;
3703 for(int i=0;i<nbOfCells;i++)
3706 getNodeIdsOfCell(i,conn);
3707 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3709 ret->setArray(array);
3711 ret->synchronizeTimeWithSupport();
3716 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3717 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3718 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3719 * from. If a result face is shared by two 3D cells, then the face in included twice in
3721 * \param [in] origin - 3 components of a point defining location of the plane.
3722 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3723 * must be greater than 1e-6.
3724 * \param [in] eps - half-thickness of the plane.
3725 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3726 * producing correspondent 2D cells. The caller is to delete this array
3727 * using decrRef() as it is no more needed.
3728 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3729 * not share the node coordinates array with \a this mesh. The caller is to
3730 * delete this mesh using decrRef() as it is no more needed.
3731 * \throw If the coordinates array is not set.
3732 * \throw If the nodal connectivity of cells is not defined.
3733 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3734 * \throw If magnitude of \a vec is less than 1e-6.
3735 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3736 * \throw If \a this includes quadratic cells.
3738 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3740 checkFullyDefined();
3741 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3742 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3744 if(candidates->empty())
3745 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3746 std::vector<int> nodes;
3747 DataArrayInt *cellIds1D=0;
3748 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3749 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3755 revDesc2=0; revDescIndx2=0;
3756 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3757 revDesc1=0; revDescIndx1=0;
3758 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3761 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3762 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3764 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3765 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3766 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3767 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3768 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3769 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3770 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3771 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3772 if(cellIds2->empty())
3773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3774 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3775 ret->setCoords(mDesc1->getCoords());
3776 ret->setConnectivity(conn,connI,true);
3777 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3782 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3783 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3784 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3786 * \param [in] origin - 3 components of a point defining location of the plane.
3787 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3788 * must be greater than 1e-6.
3789 * \param [in] eps - half-thickness of the plane.
3790 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3791 * producing correspondent segments. The caller is to delete this array
3792 * using decrRef() as it is no more needed.
3793 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3794 * mesh in 3D space. This mesh does not share the node coordinates array with
3795 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3797 * \throw If the coordinates array is not set.
3798 * \throw If the nodal connectivity of cells is not defined.
3799 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3800 * \throw If magnitude of \a vec is less than 1e-6.
3801 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3802 * \throw If \a this includes quadratic cells.
3804 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3806 checkFullyDefined();
3807 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3808 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3810 if(candidates->empty())
3811 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3812 std::vector<int> nodes;
3813 DataArrayInt *cellIds1D=0;
3814 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3815 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3820 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3821 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3824 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3825 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3827 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3828 int ncellsSub=subMesh->getNumberOfCells();
3829 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3830 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3831 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3832 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3835 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3836 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3837 for(int i=0;i<ncellsSub;i++)
3839 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3841 if(cut3DSurf[i].first!=-2)
3843 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3844 connI->pushBackSilent(conn->getNumberOfTuples());
3845 cellIds2->pushBackSilent(i);
3849 int cellId3DSurf=cut3DSurf[i].second;
3850 int offset=nodalI[cellId3DSurf]+1;
3851 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3852 for(int j=0;j<nbOfEdges;j++)
3854 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3855 connI->pushBackSilent(conn->getNumberOfTuples());
3856 cellIds2->pushBackSilent(cellId3DSurf);
3861 if(cellIds2->empty())
3862 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3863 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3864 ret->setCoords(mDesc1->getCoords());
3865 ret->setConnectivity(conn,connI,true);
3866 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3871 * Finds cells whose bounding boxes intersect a given plane.
3872 * \param [in] origin - 3 components of a point defining location of the plane.
3873 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3874 * must be greater than 1e-6.
3875 * \param [in] eps - half-thickness of the plane.
3876 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3877 * cells. The caller is to delete this array using decrRef() as it is no more
3879 * \throw If the coordinates array is not set.
3880 * \throw If the nodal connectivity of cells is not defined.
3881 * \throw If \a this->getSpaceDimension() != 3.
3882 * \throw If magnitude of \a vec is less than 1e-6.
3883 * \sa buildSlice3D()
3885 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3887 checkFullyDefined();
3888 if(getSpaceDimension()!=3)
3889 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3890 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3892 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3894 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3895 double angle=acos(vec[2]/normm);
3896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3900 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3901 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3902 if(normm2/normm>1e-6)
3903 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3904 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3906 mw->getBoundingBox(bbox);
3907 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3908 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3912 getBoundingBox(bbox);
3913 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3914 cellIds=getCellsInBoundingBox(bbox,eps);
3916 return cellIds.retn();
3920 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3921 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3922 * No consideration of coordinate is done by this method.
3923 * A 1D mesh is said contiguous if : a cell i with nodal connectivity (k,p) the cell i+1 the nodal connectivity should be (p,m)
3924 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3926 bool MEDCouplingUMesh::isContiguous1D() const
3928 if(getMeshDimension()!=1)
3929 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3930 int nbCells=getNumberOfCells();
3932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3933 const int *connI=_nodal_connec_index->getConstPointer();
3934 const int *conn=_nodal_connec->getConstPointer();
3935 int ref=conn[connI[0]+2];
3936 for(int i=1;i<nbCells;i++)
3938 if(conn[connI[i]+1]!=ref)
3940 ref=conn[connI[i]+2];
3946 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3947 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3948 * \param pt reference point of the line
3949 * \param v normalized director vector of the line
3950 * \param eps max precision before throwing an exception
3951 * \param res output of size this->getNumberOfCells
3953 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3955 if(getMeshDimension()!=1)
3956 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3957 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3958 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3959 if(getSpaceDimension()!=3)
3960 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3961 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3962 const double *fPtr=f->getArray()->getConstPointer();
3964 for(int i=0;i<getNumberOfCells();i++)
3966 const double *tmp1=fPtr+3*i;
3967 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3968 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3969 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3970 double n1=INTERP_KERNEL::norm<3>(tmp);
3971 n1/=INTERP_KERNEL::norm<3>(tmp1);
3973 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3975 const double *coo=getCoords()->getConstPointer();
3976 for(int i=0;i<getNumberOfNodes();i++)
3978 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3979 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3980 res[i]=std::accumulate(tmp,tmp+3,0.);
3985 * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance.
3986 * \a this is expected to be a mesh so that its space dimension is equal to its
3987 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3988 * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3990 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3991 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3992 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3994 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3995 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3997 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3998 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3999 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4000 * \return the positive value of the distance.
4001 * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
4003 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4005 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4007 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4008 if(meshDim!=spaceDim-1)
4009 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4010 if(meshDim!=2 && meshDim!=1)
4011 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4012 checkFullyDefined();
4013 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4014 { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
4015 DataArrayInt *ret1=0;
4016 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4017 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4019 cellId=*ret1Safe->begin();
4020 return *ret0->begin();
4024 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4025 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4026 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4027 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4028 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4030 * \a this is expected to be a mesh so that its space dimension is equal to its
4031 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4032 * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
4034 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4035 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4037 * \param [in] pts the list of points in which each tuple represents a point
4038 * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
4039 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4040 * \throw if number of components of \a pts is not equal to the space dimension.
4041 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4042 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4044 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4047 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4048 pts->checkAllocated();
4049 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4050 if(meshDim!=spaceDim-1)
4051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4052 if(meshDim!=2 && meshDim!=1)
4053 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4054 if(pts->getNumberOfComponents()!=spaceDim)
4056 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4057 throw INTERP_KERNEL::Exception(oss.str().c_str());
4059 checkFullyDefined();
4060 int nbCells=getNumberOfCells();
4062 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4063 int nbOfPts=pts->getNumberOfTuples();
4064 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4066 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4067 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4068 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4069 const double *bbox(bboxArr->begin());
4074 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4075 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4077 double x=std::numeric_limits<double>::max();
4078 std::vector<int> elems;
4079 myTree.getMinDistanceOfMax(ptsPtr,x);
4080 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4081 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4087 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4088 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4090 double x=std::numeric_limits<double>::max();
4091 std::vector<int> elems;
4092 myTree.getMinDistanceOfMax(ptsPtr,x);
4093 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4094 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4099 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4101 cellIds=ret1.retn();
4106 * \param [in] pt the start pointer (included) of the coordinates of the point
4107 * \param [in] cellIdsBg the start pointer (included) of cellIds
4108 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4109 * \param [in] nc nodal connectivity
4110 * \param [in] ncI nodal connectivity index
4111 * \param [in,out] ret0 the min distance between \a this and the external input point
4112 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4113 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4115 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4118 ret0=std::numeric_limits<double>::max();
4119 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4121 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4123 case INTERP_KERNEL::NORM_TRI3:
4125 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4127 { ret0=tmp; cellId=*zeCell; }
4130 case INTERP_KERNEL::NORM_QUAD4:
4131 case INTERP_KERNEL::NORM_POLYGON:
4133 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4135 { ret0=tmp; cellId=*zeCell; }
4139 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4145 * \param [in] pt the start pointer (included) of the coordinates of the point
4146 * \param [in] cellIdsBg the start pointer (included) of cellIds
4147 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4148 * \param [in] nc nodal connectivity
4149 * \param [in] ncI nodal connectivity index
4150 * \param [in,out] ret0 the min distance between \a this and the external input point
4151 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4152 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4154 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4157 ret0=std::numeric_limits<double>::max();
4158 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4160 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4162 case INTERP_KERNEL::NORM_SEG2:
4164 std::size_t uselessEntry=0;
4165 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4168 { ret0=tmp; cellId=*zeCell; }
4172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4178 * Finds cells in contact with a ball (i.e. a point with precision).
4179 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4180 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4182 * \warning This method is suitable if the caller intends to evaluate only one
4183 * point, for more points getCellsContainingPoints() is recommended as it is
4185 * \param [in] pos - array of coordinates of the ball central point.
4186 * \param [in] eps - ball radius.
4187 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4188 * if there are no such cells.
4189 * \throw If the coordinates array is not set.
4190 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4192 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4194 std::vector<int> elts;
4195 getCellsContainingPoint(pos,eps,elts);
4198 return elts.front();
4202 * Finds cells in contact with a ball (i.e. a point with precision).
4203 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4204 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4205 * \warning This method is suitable if the caller intends to evaluate only one
4206 * point, for more points getCellsContainingPoints() is recommended as it is
4208 * \param [in] pos - array of coordinates of the ball central point.
4209 * \param [in] eps - ball radius.
4210 * \param [out] elts - vector returning ids of the found cells. It is cleared
4211 * before inserting ids.
4212 * \throw If the coordinates array is not set.
4213 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4215 * \if ENABLE_EXAMPLES
4216 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4217 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4220 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4223 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4224 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4229 namespace ParaMEDMEM
4231 template<const int SPACEDIMM>
4235 static const int MY_SPACEDIM=SPACEDIMM;
4236 static const int MY_MESHDIM=8;
4237 typedef int MyConnType;
4238 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4240 // useless, but for windows compilation ...
4241 const double* getCoordinatesPtr() const { return 0; }
4242 const int* getConnectivityPtr() const { return 0; }
4243 const int* getConnectivityIndexPtr() const { return 0; }
4244 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4248 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4250 INTERP_KERNEL::Edge *ret(0);
4251 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4252 m[n0]=bg[0]; m[n1]=bg[1];
4255 case INTERP_KERNEL::NORM_SEG2:
4257 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4260 case INTERP_KERNEL::NORM_SEG3:
4262 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4263 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4264 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4265 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4266 bool colinearity(inters.areColinears());
4267 delete e1; delete e2;
4269 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4271 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4275 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4280 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4282 INTERP_KERNEL::Edge *ret=0;
4285 case INTERP_KERNEL::NORM_SEG2:
4287 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4290 case INTERP_KERNEL::NORM_SEG3:
4292 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4293 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4294 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4295 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4296 bool colinearity=inters.areColinears();
4297 delete e1; delete e2;
4299 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4301 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4302 mapp2[bg[2]].second=false;
4306 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4312 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4313 * the global mesh 'mDesc'.
4314 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4315 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4317 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4318 std::map<INTERP_KERNEL::Node *,int>& mapp)
4321 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4322 const double *coo=mDesc->getCoords()->getConstPointer();
4323 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4324 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4326 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4327 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4328 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4330 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4331 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4333 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4334 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4336 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4337 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4339 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4341 if((*it2).second.second)
4342 mapp[(*it2).second.first]=(*it2).first;
4343 ((*it2).second.first)->decrRef();
4348 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4352 int locId=nodeId-offset2;
4353 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4357 int locId=nodeId-offset1;
4358 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4360 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4364 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4366 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4367 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4368 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4370 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4372 int eltId1=abs(*desc1)-1;
4373 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4375 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4376 if(it==mappRev.end())
4378 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4389 template<int SPACEDIM>
4390 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4391 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4393 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4394 int *eltsIndexPtr(eltsIndex->getPointer());
4395 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4396 const double *bbox(bboxArr->begin());
4397 int nbOfCells=getNumberOfCells();
4398 const int *conn=_nodal_connec->getConstPointer();
4399 const int *connI=_nodal_connec_index->getConstPointer();
4400 double bb[2*SPACEDIM];
4401 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4402 for(int i=0;i<nbOfPoints;i++)
4404 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4405 for(int j=0;j<SPACEDIM;j++)
4407 bb[2*j]=pos[SPACEDIM*i+j];
4408 bb[2*j+1]=pos[SPACEDIM*i+j];
4410 std::vector<int> candidates;
4411 myTree.getIntersectingElems(bb,candidates);
4412 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4414 int sz(connI[(*iter)+1]-connI[*iter]-1);
4415 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4417 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4418 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4422 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4423 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4424 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4425 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4426 INTERP_KERNEL::QuadraticPolygon *pol(0);
4427 for(int j=0;j<sz;j++)
4429 int nodeId(conn[connI[*iter]+1+j]);
4430 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4432 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4433 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4435 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4436 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4437 double a(0.),b(0.),c(0.);
4438 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4439 status=pol->isInOrOut2(n);
4440 delete pol; n->decrRef();
4444 eltsIndexPtr[i+1]++;
4445 elts->pushBackSilent(*iter);
4451 * Finds cells in contact with several balls (i.e. points with precision).
4452 * This method is an extension of getCellContainingPoint() and
4453 * getCellsContainingPoint() for the case of multiple points.
4454 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4455 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4456 * \param [in] pos - an array of coordinates of points in full interlace mode :
4457 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4458 * this->getSpaceDimension() * \a nbOfPoints
4459 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4460 * \param [in] eps - radius of balls (i.e. the precision).
4461 * \param [out] elts - vector returning ids of found cells.
4462 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4463 * dividing cell ids in \a elts into groups each referring to one
4464 * point. Its every element (except the last one) is an index pointing to the
4465 * first id of a group of cells. For example cells in contact with the *i*-th
4466 * point are described by following range of indices:
4467 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4468 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4469 * Number of cells in contact with the *i*-th point is
4470 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4471 * \throw If the coordinates array is not set.
4472 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4474 * \if ENABLE_EXAMPLES
4475 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4476 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4479 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4482 int spaceDim=getSpaceDimension();
4483 int mDim=getMeshDimension();
4488 const double *coords=_coords->getConstPointer();
4489 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4496 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4498 else if(spaceDim==2)
4502 const double *coords=_coords->getConstPointer();
4503 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4506 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4508 else if(spaceDim==1)
4512 const double *coords=_coords->getConstPointer();
4513 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4516 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4519 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4523 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4524 * least two its edges intersect each other anywhere except their extremities. An
4525 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4526 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4527 * cleared before filling in.
4528 * \param [in] eps - precision.
4529 * \throw If \a this->getMeshDimension() != 2.
4530 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4532 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4534 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4535 if(getMeshDimension()!=2)
4536 throw INTERP_KERNEL::Exception(msg);
4537 int spaceDim=getSpaceDimension();
4538 if(spaceDim!=2 && spaceDim!=3)
4539 throw INTERP_KERNEL::Exception(msg);
4540 const int *conn=_nodal_connec->getConstPointer();
4541 const int *connI=_nodal_connec_index->getConstPointer();
4542 int nbOfCells=getNumberOfCells();
4543 std::vector<double> cell2DinS2;
4544 for(int i=0;i<nbOfCells;i++)
4546 int offset=connI[i];
4547 int nbOfNodesForCell=connI[i+1]-offset-1;
4548 if(nbOfNodesForCell<=3)
4550 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4551 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4552 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4559 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4561 * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown.
4562 * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too.
4564 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4565 * This convex envelop is computed using Jarvis march algorithm.
4566 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4567 * Only connectivity of some cells could be modified if those cells were not representing a convex envelop. If a cell already equals its convex envelop (regardless orientation)
4568 * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
4570 * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
4571 * \sa MEDCouplingUMesh::colinearize2D
4573 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4575 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4577 checkFullyDefined();
4578 const double *coords=getCoords()->getConstPointer();
4579 int nbOfCells=getNumberOfCells();
4580 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4581 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4582 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4583 int *workIndexOut=nodalConnecIndexOut->getPointer();
4585 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4586 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4587 std::set<INTERP_KERNEL::NormalizedCellType> types;
4588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4589 isChanged->alloc(0,1);
4590 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4592 int pos=nodalConnecOut->getNumberOfTuples();
4593 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4594 isChanged->pushBackSilent(i);
4595 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4596 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4598 if(isChanged->empty())
4600 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4602 return isChanged.retn();
4606 * This method is \b NOT const because it can modify \a this.
4607 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4608 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4609 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4610 * \b 1 for translation and rotation around point of 'mesh1D'.
4611 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4613 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4615 checkFullyDefined();
4616 mesh1D->checkFullyDefined();
4617 if(!mesh1D->isContiguous1D())
4618 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4619 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4620 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4621 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4622 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4623 if(mesh1D->getMeshDimension()!=1)
4624 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4626 if(isPresenceOfQuadratic())
4628 if(mesh1D->isFullyQuadratic())
4631 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4633 int oldNbOfNodes(getNumberOfNodes());
4634 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4639 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4644 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4648 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4650 setCoords(newCoords);
4651 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4657 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4658 * If it is not the case an exception will be thrown.
4659 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4660 * intersection of plane defined by ('origin','vec').
4661 * This method has one in/out parameter : 'cut3DCurve'.
4662 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4663 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4664 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4665 * This method will throw an exception if \a this contains a non linear segment.
4667 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4669 checkFullyDefined();
4670 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4671 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4672 int ncells=getNumberOfCells();
4673 int nnodes=getNumberOfNodes();
4674 double vec2[3],vec3[3],vec4[3];
4675 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4677 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4678 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4679 const int *conn=_nodal_connec->getConstPointer();
4680 const int *connI=_nodal_connec_index->getConstPointer();
4681 const double *coo=_coords->getConstPointer();
4682 std::vector<double> addCoo;
4683 for(int i=0;i<ncells;i++)
4685 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4687 if(cut3DCurve[i]==-2)
4689 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4690 vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4691 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4692 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4693 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4695 const double *st2=coo+3*st;
4696 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4697 double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4698 if(pos>eps && pos<1-eps)
4700 int nNode=((int)addCoo.size())/3;
4701 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4702 addCoo.insert(addCoo.end(),vec4,vec4+3);
4703 cut3DCurve[i]=nnodes+nNode;
4709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4713 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4714 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4715 coo2->alloc(newNbOfNodes,3);
4716 double *tmp=coo2->getPointer();
4717 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4718 std::copy(addCoo.begin(),addCoo.end(),tmp);
4719 DataArrayDouble::SetArrayIn(coo2,_coords);
4724 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4725 * \param mesh1D is the input 1D mesh used for translation computation.
4726 * \return newCoords new coords filled by this method.
4728 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4730 int oldNbOfNodes=getNumberOfNodes();
4731 int nbOf1DCells=mesh1D->getNumberOfCells();
4732 int spaceDim=getSpaceDimension();
4733 DataArrayDouble *ret=DataArrayDouble::New();
4734 std::vector<bool> isQuads;
4735 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4736 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4737 double *retPtr=ret->getPointer();
4738 const double *coords=getCoords()->getConstPointer();
4739 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4741 std::vector<double> c;
4745 for(int i=0;i<nbOf1DCells;i++)
4748 mesh1D->getNodeIdsOfCell(i,v);
4750 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4751 mesh1D->getCoordinatesOfNode(v[0],c);
4752 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4753 for(int j=0;j<oldNbOfNodes;j++)
4754 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4758 mesh1D->getCoordinatesOfNode(v[1],c);
4759 mesh1D->getCoordinatesOfNode(v[0],c);
4760 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4761 for(int j=0;j<oldNbOfNodes;j++)
4762 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4765 ret->copyStringInfoFrom(*getCoords());
4770 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4771 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4772 * \return newCoords new coords filled by this method.
4774 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4776 if(mesh1D->getSpaceDimension()==2)
4777 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4778 if(mesh1D->getSpaceDimension()==3)
4779 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4780 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4784 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4785 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4786 * \return newCoords new coords filled by this method.
4788 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4791 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4792 int oldNbOfNodes=getNumberOfNodes();
4793 int nbOf1DCells=mesh1D->getNumberOfCells();
4795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4796 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4797 int nbOfLevsInVec=nbOf1DCells+1;
4798 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4799 double *retPtr=ret->getPointer();
4800 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4801 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4802 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4803 tmp->setCoords(tmp2);
4804 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4805 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4806 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4807 for(int i=1;i<nbOfLevsInVec;i++)
4809 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4810 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4811 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4812 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4813 tmp->translate(vec);
4814 double tmp3[2],radius,alpha,alpha0;
4815 const double *p0=i+1<nbOfLevsInVec?begin:third;
4816 const double *p1=i+1<nbOfLevsInVec?end:begin;
4817 const double *p2=i+1<nbOfLevsInVec?third:end;
4818 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4819 double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4820 double angle=acos(cosangle/(radius*radius));
4821 tmp->rotate(end,0,angle);
4822 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4828 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4829 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4830 * \return newCoords new coords filled by this method.
4832 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4835 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4836 int oldNbOfNodes=getNumberOfNodes();
4837 int nbOf1DCells=mesh1D->getNumberOfCells();
4839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4840 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4841 int nbOfLevsInVec=nbOf1DCells+1;
4842 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4843 double *retPtr=ret->getPointer();
4844 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4845 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4846 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4847 tmp->setCoords(tmp2);
4848 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4849 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4850 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4851 for(int i=1;i<nbOfLevsInVec;i++)
4853 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4854 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4855 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4856 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4857 tmp->translate(vec);
4858 double tmp3[2],radius,alpha,alpha0;
4859 const double *p0=i+1<nbOfLevsInVec?begin:third;
4860 const double *p1=i+1<nbOfLevsInVec?end:begin;
4861 const double *p2=i+1<nbOfLevsInVec?third:end;
4862 double vecPlane[3]={
4863 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4864 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4865 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4867 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4870 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4871 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4872 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4874 double c2=cos(asin(s2));
4876 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4877 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4878 {-vec2[1]*s2, vec2[0]*s2, c2}
4880 double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4881 double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4882 double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4883 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4884 double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4885 double angle=acos(cosangle/(radius*radius));
4886 tmp->rotate(end,vecPlane,angle);
4888 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4894 * This method is private because not easy to use for end user. This method is const contrary to
4895 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4896 * the coords sorted slice by slice.
4897 * \param isQuad specifies presence of quadratic cells.
4899 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4901 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4902 int nbOf2DCells(getNumberOfCells());
4903 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4904 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4905 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4907 newConnI->alloc(nbOf3DCells+1,1);
4908 int *newConnIPtr(newConnI->getPointer());
4910 std::vector<int> newc;
4911 for(int j=0;j<nbOf2DCells;j++)
4913 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4914 *newConnIPtr++=(int)newc.size();
4916 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4917 int *newConnPtr(newConn->getPointer());
4918 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4919 newConnIPtr=newConnI->getPointer();
4920 for(int iz=0;iz<nbOf1DCells;iz++)
4923 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4924 const int *posOfTypeOfCell(newConnIPtr);
4925 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4927 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4928 if(icell!=*posOfTypeOfCell)
4931 *newConnPtr=(*iter)+iz*deltaPerLev;
4942 ret->setConnectivity(newConn,newConnI,true);
4943 ret->setCoords(getCoords());
4948 * Checks if \a this mesh is constituted by only quadratic cells.
4949 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4950 * \throw If the coordinates array is not set.
4951 * \throw If the nodal connectivity of cells is not defined.
4953 bool MEDCouplingUMesh::isFullyQuadratic() const
4955 checkFullyDefined();
4957 int nbOfCells=getNumberOfCells();
4958 for(int i=0;i<nbOfCells && ret;i++)
4960 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4961 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4962 ret=cm.isQuadratic();
4968 * Checks if \a this mesh includes any quadratic cell.
4969 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4970 * \throw If the coordinates array is not set.
4971 * \throw If the nodal connectivity of cells is not defined.
4973 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4975 checkFullyDefined();
4977 int nbOfCells=getNumberOfCells();
4978 for(int i=0;i<nbOfCells && !ret;i++)
4980 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4981 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4982 ret=cm.isQuadratic();
4988 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4989 * this mesh, it remains unchanged.
4990 * \throw If the coordinates array is not set.
4991 * \throw If the nodal connectivity of cells is not defined.
4993 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4995 checkFullyDefined();
4996 int nbOfCells=getNumberOfCells();
4998 const int *iciptr=_nodal_connec_index->getConstPointer();
4999 for(int i=0;i<nbOfCells;i++)
5001 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5002 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5003 if(cm.isQuadratic())
5005 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5006 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5007 if(!cml.isDynamic())
5008 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5010 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5017 const int *icptr=_nodal_connec->getConstPointer();
5018 newConn->alloc(getMeshLength()-delta,1);
5019 newConnI->alloc(nbOfCells+1,1);
5020 int *ocptr=newConn->getPointer();
5021 int *ociptr=newConnI->getPointer();
5024 for(int i=0;i<nbOfCells;i++,ociptr++)
5026 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5027 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5028 if(!cm.isQuadratic())
5030 _types.insert(type);
5031 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5032 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5036 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5037 _types.insert(typel);
5038 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5039 int newNbOfNodes=cml.getNumberOfNodes();
5041 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5042 *ocptr++=(int)typel;
5043 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5044 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5047 setConnectivity(newConn,newConnI,false);
5051 * This method converts all linear cell in \a this to quadratic one.
5052 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5053 * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
5054 * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
5055 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5056 * end of the existing coordinates.
5058 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5059 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5060 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5062 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5064 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5066 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5068 DataArrayInt *conn=0,*connI=0;
5069 DataArrayDouble *coords=0;
5070 std::set<INTERP_KERNEL::NormalizedCellType> types;
5071 checkFullyDefined();
5072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5073 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5074 int meshDim=getMeshDimension();
5075 switch(conversionType)
5081 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5082 connSafe=conn; connISafe=connI; coordsSafe=coords;
5085 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5086 connSafe=conn; connISafe=connI; coordsSafe=coords;
5089 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5090 connSafe=conn; connISafe=connI; coordsSafe=coords;
5093 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5101 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5102 connSafe=conn; connISafe=connI; coordsSafe=coords;
5105 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5106 connSafe=conn; connISafe=connI; coordsSafe=coords;
5109 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5110 connSafe=conn; connISafe=connI; coordsSafe=coords;
5113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5118 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5120 setConnectivity(connSafe,connISafe,false);
5122 setCoords(coordsSafe);
5128 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5129 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5130 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5131 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5132 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5133 * This method can be seen as the opposite method of colinearize2D.
5134 * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5135 * to avoid to modify the numbering of existing nodes.
5137 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5138 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5139 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5140 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5141 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5142 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5143 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5145 * \sa buildDescendingConnectivity2
5147 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5148 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5150 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5151 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5152 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5153 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5154 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5155 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5156 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5157 //DataArrayInt *out0(0),*outi0(0);
5158 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5159 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5160 //out0s=out0s->buildUnique(); out0s->sort(true);
5165 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5166 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5167 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5169 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5171 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5175 int nbOfCells=getNumberOfCells();
5176 int nbOfNodes=getNumberOfNodes();
5177 const int *cPtr=_nodal_connec->getConstPointer();
5178 const int *icPtr=_nodal_connec_index->getConstPointer();
5179 int lastVal=0,offset=nbOfNodes;
5180 for(int i=0;i<nbOfCells;i++,icPtr++)
5182 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5183 if(type==INTERP_KERNEL::NORM_SEG2)
5185 types.insert(INTERP_KERNEL::NORM_SEG3);
5186 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5187 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5188 newConn->pushBackSilent(offset++);
5190 newConnI->pushBackSilent(lastVal);
5191 ret->pushBackSilent(i);
5196 lastVal+=(icPtr[1]-icPtr[0]);
5197 newConnI->pushBackSilent(lastVal);
5198 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5202 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5206 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5212 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5213 DataArrayInt *conn1D=0,*conn1DI=0;
5214 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5215 DataArrayDouble *coordsTmp=0;
5216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5217 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5219 const int *c1DPtr=conn1D->begin();
5220 const int *c1DIPtr=conn1DI->begin();
5221 int nbOfCells=getNumberOfCells();
5222 const int *cPtr=_nodal_connec->getConstPointer();
5223 const int *icPtr=_nodal_connec_index->getConstPointer();
5225 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5227 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5228 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5229 if(!cm.isQuadratic())
5231 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5232 types.insert(typ2); newConn->pushBackSilent(typ2);
5233 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5234 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5235 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5236 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5237 newConnI->pushBackSilent(lastVal);
5238 ret->pushBackSilent(i);
5243 lastVal+=(icPtr[1]-icPtr[0]);
5244 newConnI->pushBackSilent(lastVal);
5245 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5248 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5253 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5260 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5261 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5264 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5273 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5274 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5275 DataArrayInt *conn1D=0,*conn1DI=0;
5276 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5277 DataArrayDouble *coordsTmp=0;
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5281 const int *c1DPtr=conn1D->begin();
5282 const int *c1DIPtr=conn1DI->begin();
5283 int nbOfCells=getNumberOfCells();
5284 const int *cPtr=_nodal_connec->getConstPointer();
5285 const int *icPtr=_nodal_connec_index->getConstPointer();
5286 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5287 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5289 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5290 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5291 if(!cm.isQuadratic())
5293 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5294 types.insert(typ2); newConn->pushBackSilent(typ2);
5295 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5296 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5297 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5298 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5299 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5300 newConnI->pushBackSilent(lastVal);
5301 ret->pushBackSilent(i);
5306 lastVal+=(icPtr[1]-icPtr[0]);
5307 newConnI->pushBackSilent(lastVal);
5308 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5311 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5312 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5317 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5318 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5319 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5321 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5324 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5325 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5328 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5331 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5333 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5339 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5340 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5341 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5342 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5343 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5346 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5350 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5351 int nbOfCells=getNumberOfCells();
5352 const int *cPtr=_nodal_connec->getConstPointer();
5353 const int *icPtr=_nodal_connec_index->getConstPointer();
5354 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5355 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5357 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5358 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5359 if(!cm.isQuadratic())
5361 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5362 if(typ2==INTERP_KERNEL::NORM_ERROR)
5364 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5365 throw INTERP_KERNEL::Exception(oss.str().c_str());
5367 types.insert(typ2); newConn->pushBackSilent(typ2);
5368 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5369 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5370 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5371 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5373 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5374 int tmpPos=newConn->getNumberOfTuples();
5375 newConn->pushBackSilent(nodeId2);
5376 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5378 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5379 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5380 newConnI->pushBackSilent(lastVal);
5381 ret->pushBackSilent(i);
5386 lastVal+=(icPtr[1]-icPtr[0]);
5387 newConnI->pushBackSilent(lastVal);
5388 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5393 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5394 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5395 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5396 int *c=newConn->getPointer();
5397 const int *cI(newConnI->begin());
5398 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5399 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5400 offset=coordsTmp2Safe->getNumberOfTuples();
5401 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5402 c[cI[(*elt)+1]-1]+=offset;
5403 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5408 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5409 * so that the number of cells remains the same. Quadratic faces are converted to
5410 * polygons. This method works only for 2D meshes in
5411 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5412 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5413 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5414 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5415 * a polylinized edge constituting the input polygon.
5416 * \throw If the coordinates array is not set.
5417 * \throw If the nodal connectivity of cells is not defined.
5418 * \throw If \a this->getMeshDimension() != 2.
5419 * \throw If \a this->getSpaceDimension() != 2.
5421 void MEDCouplingUMesh::tessellate2D(double eps)
5423 checkFullyDefined();
5424 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5426 double epsa=fabs(eps);
5427 if(epsa<std::numeric_limits<double>::min())
5428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5433 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5434 revDesc1=0; revDescIndx1=0;
5435 mDesc->tessellate2DCurve(eps);
5436 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5437 setCoords(mDesc->getCoords());
5441 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5442 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5443 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5444 * a sub-divided edge.
5445 * \throw If the coordinates array is not set.
5446 * \throw If the nodal connectivity of cells is not defined.
5447 * \throw If \a this->getMeshDimension() != 1.
5448 * \throw If \a this->getSpaceDimension() != 2.
5450 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5452 checkFullyDefined();
5453 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5455 double epsa=fabs(eps);
5456 if(epsa<std::numeric_limits<double>::min())
5457 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5458 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5459 int nbCells=getNumberOfCells();
5460 int nbNodes=getNumberOfNodes();
5461 const int *conn=_nodal_connec->getConstPointer();
5462 const int *connI=_nodal_connec_index->getConstPointer();
5463 const double *coords=_coords->getConstPointer();
5464 std::vector<double> addCoo;
5465 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5467 newConnI->alloc(nbCells+1,1);
5468 int *newConnIPtr=newConnI->getPointer();
5471 INTERP_KERNEL::Node *tmp2[3];
5472 std::set<INTERP_KERNEL::NormalizedCellType> types;
5473 for(int i=0;i<nbCells;i++,newConnIPtr++)
5475 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5476 if(cm.isQuadratic())
5477 {//assert(connI[i+1]-connI[i]-1==3)
5478 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5479 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5480 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5481 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5482 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5485 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5486 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5488 newConnIPtr[1]=(int)newConn.size();
5492 types.insert(INTERP_KERNEL::NORM_SEG2);
5493 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5494 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5495 newConnIPtr[1]=newConnIPtr[0]+3;
5500 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5501 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5502 newConnIPtr[1]=newConnIPtr[0]+3;
5505 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5508 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5510 newConnArr->alloc((int)newConn.size(),1);
5511 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5512 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5513 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5514 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5515 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5516 std::copy(addCoo.begin(),addCoo.end(),work);
5517 DataArrayDouble::SetArrayIn(newCoords,_coords);
5522 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5523 * In addition, returns an array mapping new cells to old ones. <br>
5524 * This method typically increases the number of cells in \a this mesh
5525 * but the number of nodes remains \b unchanged.
5526 * That's why the 3D splitting policies
5527 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5528 * \param [in] policy - specifies a pattern used for splitting.
5529 * The semantic of \a policy is:
5530 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5531 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5532 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5533 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5534 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5535 * an id of old cell producing it. The caller is to delete this array using
5536 * decrRef() as it is no more needed.
5537 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5538 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5539 * and \a this->getMeshDimension() != 3.
5540 * \throw If \a policy is not one of the four discussed above.
5541 * \throw If the nodal connectivity of cells is not defined.
5542 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5544 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5549 return simplexizePol0();
5551 return simplexizePol1();
5552 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5553 return simplexizePlanarFace5();
5554 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5555 return simplexizePlanarFace6();
5557 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)");
5562 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5563 * - 1D: INTERP_KERNEL::NORM_SEG2
5564 * - 2D: INTERP_KERNEL::NORM_TRI3
5565 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5567 * This method is useful for users that need to use P1 field services as
5568 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5569 * All these methods need mesh support containing only simplex cells.
5570 * \return bool - \c true if there are only simplex cells in \a this mesh.
5571 * \throw If the coordinates array is not set.
5572 * \throw If the nodal connectivity of cells is not defined.
5573 * \throw If \a this->getMeshDimension() < 1.
5575 bool MEDCouplingUMesh::areOnlySimplexCells() const
5577 checkFullyDefined();
5578 int mdim=getMeshDimension();
5579 if(mdim<1 || mdim>3)
5580 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5581 int nbCells=getNumberOfCells();
5582 const int *conn=_nodal_connec->getConstPointer();
5583 const int *connI=_nodal_connec_index->getConstPointer();
5584 for(int i=0;i<nbCells;i++)
5586 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5594 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5596 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5598 checkConnectivityFullyDefined();
5599 if(getMeshDimension()!=2)
5600 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5601 int nbOfCells=getNumberOfCells();
5602 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5603 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5604 ret->alloc(nbOfCells+nbOfCutCells,1);
5605 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5606 int *retPt=ret->getPointer();
5607 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5608 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5609 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5610 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5611 int *pt=newConn->getPointer();
5612 int *ptI=newConnI->getPointer();
5614 const int *oldc=_nodal_connec->getConstPointer();
5615 const int *ci=_nodal_connec_index->getConstPointer();
5616 for(int i=0;i<nbOfCells;i++,ci++)
5618 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5620 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5621 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5622 pt=std::copy(tmp,tmp+8,pt);
5631 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5632 ptI[1]=ptI[0]+ci[1]-ci[0];
5637 _nodal_connec->decrRef();
5638 _nodal_connec=newConn.retn();
5639 _nodal_connec_index->decrRef();
5640 _nodal_connec_index=newConnI.retn();
5647 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5649 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5651 checkConnectivityFullyDefined();
5652 if(getMeshDimension()!=2)
5653 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5654 int nbOfCells=getNumberOfCells();
5655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5656 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5657 ret->alloc(nbOfCells+nbOfCutCells,1);
5658 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5659 int *retPt=ret->getPointer();
5660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5662 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5663 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5664 int *pt=newConn->getPointer();
5665 int *ptI=newConnI->getPointer();
5667 const int *oldc=_nodal_connec->getConstPointer();
5668 const int *ci=_nodal_connec_index->getConstPointer();
5669 for(int i=0;i<nbOfCells;i++,ci++)
5671 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5673 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5674 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5675 pt=std::copy(tmp,tmp+8,pt);
5684 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5685 ptI[1]=ptI[0]+ci[1]-ci[0];
5690 _nodal_connec->decrRef();
5691 _nodal_connec=newConn.retn();
5692 _nodal_connec_index->decrRef();
5693 _nodal_connec_index=newConnI.retn();
5700 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5702 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5704 checkConnectivityFullyDefined();
5705 if(getMeshDimension()!=3)
5706 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5707 int nbOfCells=getNumberOfCells();
5708 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5709 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5710 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5711 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5712 int *retPt=ret->getPointer();
5713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5715 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5716 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5717 int *pt=newConn->getPointer();
5718 int *ptI=newConnI->getPointer();
5720 const int *oldc=_nodal_connec->getConstPointer();
5721 const int *ci=_nodal_connec_index->getConstPointer();
5722 for(int i=0;i<nbOfCells;i++,ci++)
5724 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5726 for(int j=0;j<5;j++,pt+=5,ptI++)
5728 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5729 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];
5736 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5737 ptI[1]=ptI[0]+ci[1]-ci[0];
5742 _nodal_connec->decrRef();
5743 _nodal_connec=newConn.retn();
5744 _nodal_connec_index->decrRef();
5745 _nodal_connec_index=newConnI.retn();
5752 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5754 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5756 checkConnectivityFullyDefined();
5757 if(getMeshDimension()!=3)
5758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5759 int nbOfCells=getNumberOfCells();
5760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5761 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5762 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5763 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5764 int *retPt=ret->getPointer();
5765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5767 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5768 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5769 int *pt=newConn->getPointer();
5770 int *ptI=newConnI->getPointer();
5772 const int *oldc=_nodal_connec->getConstPointer();
5773 const int *ci=_nodal_connec_index->getConstPointer();
5774 for(int i=0;i<nbOfCells;i++,ci++)
5776 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5778 for(int j=0;j<6;j++,pt+=5,ptI++)
5780 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5781 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];
5788 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5789 ptI[1]=ptI[0]+ci[1]-ci[0];
5794 _nodal_connec->decrRef();
5795 _nodal_connec=newConn.retn();
5796 _nodal_connec_index->decrRef();
5797 _nodal_connec_index=newConnI.retn();
5804 * 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.
5805 * This method completly ignore coordinates.
5806 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5807 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5808 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5809 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5811 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5813 checkFullyDefined();
5814 if(getMeshDimension()!=2)
5815 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5816 int nbOfCells=getNumberOfCells();
5817 int *connI=_nodal_connec_index->getPointer();
5819 for(int i=0;i<nbOfCells;i++,connI++)
5821 int offset=descIndex[i];
5822 int nbOfEdges=descIndex[i+1]-offset;
5824 bool ddirect=desc[offset+nbOfEdges-1]>0;
5825 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5826 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5827 for(int j=0;j<nbOfEdges;j++)
5829 bool direct=desc[offset+j]>0;
5830 int edgeId=std::abs(desc[offset+j])-1;
5831 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5833 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5834 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5835 int ref2=direct?id1:id2;
5838 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5839 newConnLgth+=nbOfSubNodes-1;
5844 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5845 throw INTERP_KERNEL::Exception(oss.str().c_str());
5850 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5853 newConnLgth++;//+1 is for cell type
5854 connI[1]=newConnLgth;
5857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5858 newConn->alloc(newConnLgth,1);
5859 int *work=newConn->getPointer();
5860 for(int i=0;i<nbOfCells;i++)
5862 *work++=INTERP_KERNEL::NORM_POLYGON;
5863 int offset=descIndex[i];
5864 int nbOfEdges=descIndex[i+1]-offset;
5865 for(int j=0;j<nbOfEdges;j++)
5867 bool direct=desc[offset+j]>0;
5868 int edgeId=std::abs(desc[offset+j])-1;
5870 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5873 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5874 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5875 work=std::copy(it,it+nbOfSubNodes-1,work);
5879 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5882 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5886 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5887 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5888 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5889 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5890 * so it can be useful to call mergeNodes() before calling this method.
5891 * \throw If \a this->getMeshDimension() <= 1.
5892 * \throw If the coordinates array is not set.
5893 * \throw If the nodal connectivity of cells is not defined.
5895 void MEDCouplingUMesh::convertDegeneratedCells()
5897 checkFullyDefined();
5898 if(getMeshDimension()<=1)
5899 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5900 int nbOfCells=getNumberOfCells();
5903 int initMeshLgth=getMeshLength();
5904 int *conn=_nodal_connec->getPointer();
5905 int *index=_nodal_connec_index->getPointer();
5909 for(int i=0;i<nbOfCells;i++)
5911 lgthOfCurCell=index[i+1]-posOfCurCell;
5912 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5914 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5915 conn+newPos+1,newLgth);
5916 conn[newPos]=newType;
5918 posOfCurCell=index[i+1];
5921 if(newPos!=initMeshLgth)
5922 _nodal_connec->reAlloc(newPos);
5927 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5928 * A cell is considered to be oriented correctly if an angle between its
5929 * normal vector and a given vector is less than \c PI / \c 2.
5930 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5932 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5934 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5935 * is not cleared before filling in.
5936 * \throw If \a this->getMeshDimension() != 2.
5937 * \throw If \a this->getSpaceDimension() != 3.
5939 * \if ENABLE_EXAMPLES
5940 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5941 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5944 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5946 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5947 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5948 int nbOfCells=getNumberOfCells();
5949 const int *conn=_nodal_connec->getConstPointer();
5950 const int *connI=_nodal_connec_index->getConstPointer();
5951 const double *coordsPtr=_coords->getConstPointer();
5952 for(int i=0;i<nbOfCells;i++)
5954 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5955 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5957 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5958 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5965 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5966 * considered to be oriented correctly if an angle between its normal vector and a
5967 * given vector is less than \c PI / \c 2.
5968 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5970 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5972 * \throw If \a this->getMeshDimension() != 2.
5973 * \throw If \a this->getSpaceDimension() != 3.
5975 * \if ENABLE_EXAMPLES
5976 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5977 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5980 * \sa changeOrientationOfCells
5982 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5984 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5985 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5986 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5987 const int *connI(_nodal_connec_index->getConstPointer());
5988 const double *coordsPtr(_coords->getConstPointer());
5989 bool isModified(false);
5990 for(int i=0;i<nbOfCells;i++)
5992 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5993 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5995 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5996 bool isQuadratic(cm.isQuadratic());
5997 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6000 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6005 _nodal_connec->declareAsNew();
6010 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6012 * \sa orientCorrectly2DCells
6014 void MEDCouplingUMesh::changeOrientationOfCells()
6016 int mdim(getMeshDimension());
6017 if(mdim!=2 && mdim!=1)
6018 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6019 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6020 const int *connI(_nodal_connec_index->getConstPointer());
6023 for(int i=0;i<nbOfCells;i++)
6025 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6026 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6027 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6032 for(int i=0;i<nbOfCells;i++)
6034 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6035 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6036 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6042 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6043 * oriented facets. The normal vector of the facet should point out of the cell.
6044 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6045 * is not cleared before filling in.
6046 * \throw If \a this->getMeshDimension() != 3.
6047 * \throw If \a this->getSpaceDimension() != 3.
6048 * \throw If the coordinates array is not set.
6049 * \throw If the nodal connectivity of cells is not defined.
6051 * \if ENABLE_EXAMPLES
6052 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6053 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6056 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6058 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6059 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6060 int nbOfCells=getNumberOfCells();
6061 const int *conn=_nodal_connec->getConstPointer();
6062 const int *connI=_nodal_connec_index->getConstPointer();
6063 const double *coordsPtr=_coords->getConstPointer();
6064 for(int i=0;i<nbOfCells;i++)
6066 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6067 if(type==INTERP_KERNEL::NORM_POLYHED)
6069 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6076 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6078 * \throw If \a this->getMeshDimension() != 3.
6079 * \throw If \a this->getSpaceDimension() != 3.
6080 * \throw If the coordinates array is not set.
6081 * \throw If the nodal connectivity of cells is not defined.
6082 * \throw If the reparation fails.
6084 * \if ENABLE_EXAMPLES
6085 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6086 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6088 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6090 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6092 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6093 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6094 int nbOfCells=getNumberOfCells();
6095 int *conn=_nodal_connec->getPointer();
6096 const int *connI=_nodal_connec_index->getConstPointer();
6097 const double *coordsPtr=_coords->getConstPointer();
6098 for(int i=0;i<nbOfCells;i++)
6100 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6101 if(type==INTERP_KERNEL::NORM_POLYHED)
6105 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6106 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6108 catch(INTERP_KERNEL::Exception& e)
6110 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6111 throw INTERP_KERNEL::Exception(oss.str().c_str());
6119 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6120 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6121 * according to which the first facet of the cell should be oriented to have the normal vector
6122 * pointing out of cell.
6123 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6124 * cells. The caller is to delete this array using decrRef() as it is no more
6126 * \throw If \a this->getMeshDimension() != 3.
6127 * \throw If \a this->getSpaceDimension() != 3.
6128 * \throw If the coordinates array is not set.
6129 * \throw If the nodal connectivity of cells is not defined.
6131 * \if ENABLE_EXAMPLES
6132 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6133 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6135 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6137 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6139 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6140 if(getMeshDimension()!=3)
6141 throw INTERP_KERNEL::Exception(msg);
6142 int spaceDim=getSpaceDimension();
6144 throw INTERP_KERNEL::Exception(msg);
6146 int nbOfCells=getNumberOfCells();
6147 int *conn=_nodal_connec->getPointer();
6148 const int *connI=_nodal_connec_index->getConstPointer();
6149 const double *coo=getCoords()->getConstPointer();
6150 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6151 for(int i=0;i<nbOfCells;i++)
6153 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6154 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6156 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6158 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6159 cells->pushBackSilent(i);
6163 return cells.retn();
6167 * This method is a faster method to correct orientation of all 3D cells in \a this.
6168 * 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.
6169 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6171 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6172 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6174 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6176 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6177 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6178 int nbOfCells=getNumberOfCells();
6179 int *conn=_nodal_connec->getPointer();
6180 const int *connI=_nodal_connec_index->getConstPointer();
6181 const double *coordsPtr=_coords->getConstPointer();
6182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6183 for(int i=0;i<nbOfCells;i++)
6185 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6188 case INTERP_KERNEL::NORM_TETRA4:
6190 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6192 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6193 ret->pushBackSilent(i);
6197 case INTERP_KERNEL::NORM_PYRA5:
6199 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6201 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6202 ret->pushBackSilent(i);
6206 case INTERP_KERNEL::NORM_PENTA6:
6207 case INTERP_KERNEL::NORM_HEXA8:
6208 case INTERP_KERNEL::NORM_HEXGP12:
6210 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6212 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6213 ret->pushBackSilent(i);
6217 case INTERP_KERNEL::NORM_POLYHED:
6219 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6221 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6222 ret->pushBackSilent(i);
6227 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 !");
6235 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6236 * If it is not the case an exception will be thrown.
6237 * This method is fast because the first cell of \a this is used to compute the plane.
6238 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6239 * \param pos output of size at least 3 used to store a point owned of searched plane.
6241 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6243 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6244 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6245 const int *conn=_nodal_connec->getConstPointer();
6246 const int *connI=_nodal_connec_index->getConstPointer();
6247 const double *coordsPtr=_coords->getConstPointer();
6248 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6249 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6253 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6254 * cells. Currently cells of the following types are treated:
6255 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6256 * For a cell of other type an exception is thrown.
6257 * Space dimension of a 2D mesh can be either 2 or 3.
6258 * The Edge Ratio of a cell \f$t\f$ is:
6259 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6260 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6261 * the smallest edge lengths of \f$t\f$.
6262 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6263 * cells and one time, lying on \a this mesh. The caller is to delete this
6264 * field using decrRef() as it is no more needed.
6265 * \throw If the coordinates array is not set.
6266 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6267 * \throw If the connectivity data array has more than one component.
6268 * \throw If the connectivity data array has a named component.
6269 * \throw If the connectivity index data array has more than one component.
6270 * \throw If the connectivity index data array has a named component.
6271 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6272 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6273 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6275 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6278 int spaceDim=getSpaceDimension();
6279 int meshDim=getMeshDimension();
6280 if(spaceDim!=2 && spaceDim!=3)
6281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6282 if(meshDim!=2 && meshDim!=3)
6283 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6284 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6286 int nbOfCells=getNumberOfCells();
6287 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6288 arr->alloc(nbOfCells,1);
6289 double *pt=arr->getPointer();
6290 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6291 const int *conn=_nodal_connec->getConstPointer();
6292 const int *connI=_nodal_connec_index->getConstPointer();
6293 const double *coo=_coords->getConstPointer();
6295 for(int i=0;i<nbOfCells;i++,pt++)
6297 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6300 case INTERP_KERNEL::NORM_TRI3:
6302 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6303 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6306 case INTERP_KERNEL::NORM_QUAD4:
6308 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6309 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6312 case INTERP_KERNEL::NORM_TETRA4:
6314 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6315 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6321 conn+=connI[i+1]-connI[i];
6323 ret->setName("EdgeRatio");
6324 ret->synchronizeTimeWithSupport();
6329 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6330 * cells. Currently cells of the following types are treated:
6331 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6332 * For a cell of other type an exception is thrown.
6333 * Space dimension of a 2D mesh can be either 2 or 3.
6334 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6335 * cells and one time, lying on \a this mesh. The caller is to delete this
6336 * field using decrRef() as it is no more needed.
6337 * \throw If the coordinates array is not set.
6338 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6339 * \throw If the connectivity data array has more than one component.
6340 * \throw If the connectivity data array has a named component.
6341 * \throw If the connectivity index data array has more than one component.
6342 * \throw If the connectivity index data array has a named component.
6343 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6344 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6345 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6347 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6350 int spaceDim=getSpaceDimension();
6351 int meshDim=getMeshDimension();
6352 if(spaceDim!=2 && spaceDim!=3)
6353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6354 if(meshDim!=2 && meshDim!=3)
6355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6358 int nbOfCells=getNumberOfCells();
6359 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6360 arr->alloc(nbOfCells,1);
6361 double *pt=arr->getPointer();
6362 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6363 const int *conn=_nodal_connec->getConstPointer();
6364 const int *connI=_nodal_connec_index->getConstPointer();
6365 const double *coo=_coords->getConstPointer();
6367 for(int i=0;i<nbOfCells;i++,pt++)
6369 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6372 case INTERP_KERNEL::NORM_TRI3:
6374 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6375 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6378 case INTERP_KERNEL::NORM_QUAD4:
6380 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6381 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6384 case INTERP_KERNEL::NORM_TETRA4:
6386 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6387 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6391 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6393 conn+=connI[i+1]-connI[i];
6395 ret->setName("AspectRatio");
6396 ret->synchronizeTimeWithSupport();
6401 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6402 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6403 * treated: INTERP_KERNEL::NORM_QUAD4.
6404 * For a cell of other type an exception is thrown.
6405 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6406 * cells and one time, lying on \a this mesh. The caller is to delete this
6407 * field using decrRef() as it is no more needed.
6408 * \throw If the coordinates array is not set.
6409 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6410 * \throw If the connectivity data array has more than one component.
6411 * \throw If the connectivity data array has a named component.
6412 * \throw If the connectivity index data array has more than one component.
6413 * \throw If the connectivity index data array has a named component.
6414 * \throw If \a this->getMeshDimension() != 2.
6415 * \throw If \a this->getSpaceDimension() != 3.
6416 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6418 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6421 int spaceDim=getSpaceDimension();
6422 int meshDim=getMeshDimension();
6424 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6427 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6429 int nbOfCells=getNumberOfCells();
6430 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6431 arr->alloc(nbOfCells,1);
6432 double *pt=arr->getPointer();
6433 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6434 const int *conn=_nodal_connec->getConstPointer();
6435 const int *connI=_nodal_connec_index->getConstPointer();
6436 const double *coo=_coords->getConstPointer();
6438 for(int i=0;i<nbOfCells;i++,pt++)
6440 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6443 case INTERP_KERNEL::NORM_QUAD4:
6445 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6446 *pt=INTERP_KERNEL::quadWarp(tmp);
6450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6452 conn+=connI[i+1]-connI[i];
6454 ret->setName("Warp");
6455 ret->synchronizeTimeWithSupport();
6461 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6462 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6463 * treated: INTERP_KERNEL::NORM_QUAD4.
6464 * For a cell of other type an exception is thrown.
6465 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6466 * cells and one time, lying on \a this mesh. The caller is to delete this
6467 * field using decrRef() as it is no more needed.
6468 * \throw If the coordinates array is not set.
6469 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6470 * \throw If the connectivity data array has more than one component.
6471 * \throw If the connectivity data array has a named component.
6472 * \throw If the connectivity index data array has more than one component.
6473 * \throw If the connectivity index data array has a named component.
6474 * \throw If \a this->getMeshDimension() != 2.
6475 * \throw If \a this->getSpaceDimension() != 3.
6476 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6478 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6481 int spaceDim=getSpaceDimension();
6482 int meshDim=getMeshDimension();
6484 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6486 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6487 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6489 int nbOfCells=getNumberOfCells();
6490 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6491 arr->alloc(nbOfCells,1);
6492 double *pt=arr->getPointer();
6493 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6494 const int *conn=_nodal_connec->getConstPointer();
6495 const int *connI=_nodal_connec_index->getConstPointer();
6496 const double *coo=_coords->getConstPointer();
6498 for(int i=0;i<nbOfCells;i++,pt++)
6500 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6503 case INTERP_KERNEL::NORM_QUAD4:
6505 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6506 *pt=INTERP_KERNEL::quadSkew(tmp);
6510 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6512 conn+=connI[i+1]-connI[i];
6514 ret->setName("Skew");
6515 ret->synchronizeTimeWithSupport();
6520 * 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.
6522 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6524 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6526 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6529 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6531 std::set<INTERP_KERNEL::NormalizedCellType> types;
6532 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6533 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6534 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6535 arr->alloc(nbCells,1);
6536 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6538 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6540 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6543 ret->setName("Diameter");
6548 * This method aggregate the bbox of each cell and put it into bbox parameter.
6550 * \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)
6551 * For all other cases this input parameter is ignored.
6552 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6554 * \throw If \a this is not fully set (coordinates and connectivity).
6555 * \throw If a cell in \a this has no valid nodeId.
6556 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6558 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6560 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6561 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.
6562 return getBoundingBoxForBBTreeFast();
6563 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6565 bool presenceOfQuadratic(false);
6566 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6568 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6569 if(cm.isQuadratic())
6570 presenceOfQuadratic=true;
6572 if(!presenceOfQuadratic)
6573 return getBoundingBoxForBBTreeFast();
6574 if(mDim==2 && sDim==2)
6575 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6577 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6579 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) !");
6583 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6584 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6586 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6588 * \throw If \a this is not fully set (coordinates and connectivity).
6589 * \throw If a cell in \a this has no valid nodeId.
6591 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6593 checkFullyDefined();
6594 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6595 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6596 double *bbox(ret->getPointer());
6597 for(int i=0;i<nbOfCells*spaceDim;i++)
6599 bbox[2*i]=std::numeric_limits<double>::max();
6600 bbox[2*i+1]=-std::numeric_limits<double>::max();
6602 const double *coordsPtr(_coords->getConstPointer());
6603 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6604 for(int i=0;i<nbOfCells;i++)
6606 int offset=connI[i]+1;
6607 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6608 for(int j=0;j<nbOfNodesForCell;j++)
6610 int nodeId=conn[offset+j];
6611 if(nodeId>=0 && nodeId<nbOfNodes)
6613 for(int k=0;k<spaceDim;k++)
6615 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6616 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6623 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6624 throw INTERP_KERNEL::Exception(oss.str().c_str());
6631 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6632 * useful for 2D meshes having quadratic cells
6633 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6634 * the two extremities of the arc of circle).
6636 * \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)
6637 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6638 * \throw If \a this is not fully defined.
6639 * \throw If \a this is not a mesh with meshDimension equal to 2.
6640 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6641 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6643 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6645 checkFullyDefined();
6646 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6647 if(spaceDim!=2 || mDim!=2)
6648 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!");
6649 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6650 double *bbox(ret->getPointer());
6651 const double *coords(_coords->getConstPointer());
6652 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6653 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6655 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6656 int sz(connI[1]-connI[0]-1);
6657 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6658 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6659 INTERP_KERNEL::QuadraticPolygon *pol(0);
6660 for(int j=0;j<sz;j++)
6662 int nodeId(conn[*connI+1+j]);
6663 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6665 if(!cm.isQuadratic())
6666 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6668 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6669 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6670 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6676 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6677 * useful for 2D meshes having quadratic cells
6678 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6679 * the two extremities of the arc of circle).
6681 * \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)
6682 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6683 * \throw If \a this is not fully defined.
6684 * \throw If \a this is not a mesh with meshDimension equal to 1.
6685 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6686 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6688 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6690 checkFullyDefined();
6691 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6692 if(spaceDim!=2 || mDim!=1)
6693 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!");
6694 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6695 double *bbox(ret->getPointer());
6696 const double *coords(_coords->getConstPointer());
6697 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6698 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6700 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6701 int sz(connI[1]-connI[0]-1);
6702 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6703 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6704 INTERP_KERNEL::Edge *edge(0);
6705 for(int j=0;j<sz;j++)
6707 int nodeId(conn[*connI+1+j]);
6708 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6710 if(!cm.isQuadratic())
6711 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6713 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6714 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6715 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6722 namespace ParaMEDMEMImpl
6727 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6728 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6737 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6738 bool operator() (const int& pos) { return _conn[pos]==_val; }
6748 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6749 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6750 * \a this is composed in cell types.
6751 * The returned array is of size 3*n where n is the number of different types present in \a this.
6752 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6753 * This parameter is kept only for compatibility with other methode listed above.
6755 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6757 checkConnectivityFullyDefined();
6758 const int *conn=_nodal_connec->getConstPointer();
6759 const int *connI=_nodal_connec_index->getConstPointer();
6760 const int *work=connI;
6761 int nbOfCells=getNumberOfCells();
6762 std::size_t n=getAllGeoTypes().size();
6763 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6764 std::set<INTERP_KERNEL::NormalizedCellType> types;
6765 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6767 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6768 if(types.find(typ)!=types.end())
6770 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6771 oss << " is not contiguous !";
6772 throw INTERP_KERNEL::Exception(oss.str().c_str());
6776 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6777 ret[3*i+1]=(int)std::distance(work,work2);
6784 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6785 * only for types cell, type node is not managed.
6786 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6787 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6788 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6789 * If 2 or more same geometric type is in \a code and exception is thrown too.
6791 * This method firstly checks
6792 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6793 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6794 * an exception is thrown too.
6796 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6797 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6798 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6800 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6803 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6804 std::size_t sz=code.size();
6807 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6808 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6810 bool isNoPflUsed=true;
6811 for(std::size_t i=0;i<n;i++)
6812 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6814 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6816 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6817 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6818 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6821 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6824 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6825 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6826 if(types.size()==_types.size())
6829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6831 int *retPtr=ret->getPointer();
6832 const int *connI=_nodal_connec_index->getConstPointer();
6833 const int *conn=_nodal_connec->getConstPointer();
6834 int nbOfCells=getNumberOfCells();
6837 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6839 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6840 int offset=(int)std::distance(connI,i);
6841 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6842 int nbOfCellsOfCurType=(int)std::distance(i,j);
6843 if(code[3*kk+2]==-1)
6844 for(int k=0;k<nbOfCellsOfCurType;k++)
6848 int idInIdsPerType=code[3*kk+2];
6849 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6851 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6854 zePfl->checkAllocated();
6855 if(zePfl->getNumberOfComponents()==1)
6857 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6859 if(*k>=0 && *k<nbOfCellsOfCurType)
6860 *retPtr=(*k)+offset;
6863 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6864 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6865 throw INTERP_KERNEL::Exception(oss.str().c_str());
6870 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6877 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6878 oss << " should be in [0," << idsPerType.size() << ") !";
6879 throw INTERP_KERNEL::Exception(oss.str().c_str());
6888 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6889 * 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.
6890 * 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.
6891 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6893 * \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.
6894 * \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,
6895 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6896 * \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.
6897 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6898 * \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
6900 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6904 if(profile->getNumberOfComponents()!=1)
6905 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6906 checkConnectivityFullyDefined();
6907 const int *conn=_nodal_connec->getConstPointer();
6908 const int *connI=_nodal_connec_index->getConstPointer();
6909 int nbOfCells=getNumberOfCells();
6910 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6911 std::vector<int> typeRangeVals(1);
6912 for(const int *i=connI;i!=connI+nbOfCells;)
6914 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6915 if(std::find(types.begin(),types.end(),curType)!=types.end())
6917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6919 types.push_back(curType);
6920 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6921 typeRangeVals.push_back((int)std::distance(connI,i));
6924 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6925 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6927 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6930 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6931 code.resize(3*nbOfCastsFinal);
6932 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6933 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6934 for(int i=0;i<nbOfCastsFinal;i++)
6936 int castId=castsPresent->getIJ(i,0);
6937 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6938 idsInPflPerType2.push_back(tmp3);
6939 code[3*i]=(int)types[castId];
6940 code[3*i+1]=tmp3->getNumberOfTuples();
6941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6942 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6944 tmp4->copyStringInfoFrom(*profile);
6945 idsPerType2.push_back(tmp4);
6946 code[3*i+2]=(int)idsPerType2.size()-1;
6953 std::size_t sz2=idsInPflPerType2.size();
6954 idsInPflPerType.resize(sz2);
6955 for(std::size_t i=0;i<sz2;i++)
6957 DataArrayInt *locDa=idsInPflPerType2[i];
6959 idsInPflPerType[i]=locDa;
6961 std::size_t sz=idsPerType2.size();
6962 idsPerType.resize(sz);
6963 for(std::size_t i=0;i<sz;i++)
6965 DataArrayInt *locDa=idsPerType2[i];
6967 idsPerType[i]=locDa;
6972 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6973 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6974 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6975 * 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.
6977 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6979 checkFullyDefined();
6980 nM1LevMesh->checkFullyDefined();
6981 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6982 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6983 if(_coords!=nM1LevMesh->getCoords())
6984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6985 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6987 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6989 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6990 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6991 tmp->setConnectivity(tmp0,tmp1);
6992 tmp->renumberCells(ret0->getConstPointer(),false);
6993 revDesc=tmp->getNodalConnectivity();
6994 revDescIndx=tmp->getNodalConnectivityIndex();
6995 DataArrayInt *ret=0;
6996 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6999 ret->getMaxValue(tmp2);
7001 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7002 throw INTERP_KERNEL::Exception(oss.str().c_str());
7007 revDescIndx->incrRef();
7010 meshnM1Old2New=ret0;
7015 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7016 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7017 * in "Old to New" mode.
7018 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7019 * this array using decrRef() as it is no more needed.
7020 * \throw If the nodal connectivity of cells is not defined.
7022 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7024 checkConnectivityFullyDefined();
7025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7026 renumberCells(ret->getConstPointer(),false);
7031 * This methods checks that cells are sorted by their types.
7032 * This method makes asumption (no check) that connectivity is correctly set before calling.
7034 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7036 checkFullyDefined();
7037 const int *conn=_nodal_connec->getConstPointer();
7038 const int *connI=_nodal_connec_index->getConstPointer();
7039 int nbOfCells=getNumberOfCells();
7040 std::set<INTERP_KERNEL::NormalizedCellType> types;
7041 for(const int *i=connI;i!=connI+nbOfCells;)
7043 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7044 if(types.find(curType)!=types.end())
7046 types.insert(curType);
7047 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7053 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7054 * The geometric type order is specified by MED file.
7056 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7058 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7060 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7064 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7065 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7066 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7067 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7069 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7071 checkFullyDefined();
7072 const int *conn=_nodal_connec->getConstPointer();
7073 const int *connI=_nodal_connec_index->getConstPointer();
7074 int nbOfCells=getNumberOfCells();
7078 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7079 for(const int *i=connI;i!=connI+nbOfCells;)
7081 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7082 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7083 if(isTypeExists!=orderEnd)
7085 int pos=(int)std::distance(orderBg,isTypeExists);
7089 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7093 if(sg.find(curType)==sg.end())
7095 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7106 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7107 * 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
7108 * 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'.
7110 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7112 checkConnectivityFullyDefined();
7113 int nbOfCells=getNumberOfCells();
7114 const int *conn=_nodal_connec->getConstPointer();
7115 const int *connI=_nodal_connec_index->getConstPointer();
7116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7117 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7118 tmpa->alloc(nbOfCells,1);
7119 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7120 tmpb->fillWithZero();
7121 int *tmp=tmpa->getPointer();
7122 int *tmp2=tmpb->getPointer();
7123 for(const int *i=connI;i!=connI+nbOfCells;i++)
7125 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7128 int pos=(int)std::distance(orderBg,where);
7130 tmp[std::distance(connI,i)]=pos;
7134 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7135 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7136 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7137 throw INTERP_KERNEL::Exception(oss.str().c_str());
7140 nbPerType=tmpb.retn();
7145 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7147 * \return a new object containing the old to new correspondance.
7149 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7151 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7153 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7157 * 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.
7158 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7159 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7160 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7162 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7164 DataArrayInt *nbPerType=0;
7165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7166 nbPerType->decrRef();
7167 return tmpa->buildPermArrPerLevel();
7171 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7172 * The number of cells remains unchanged after the call of this method.
7173 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7174 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7176 * \return the array giving the correspondance old to new.
7178 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7180 checkFullyDefined();
7182 const int *conn=_nodal_connec->getConstPointer();
7183 const int *connI=_nodal_connec_index->getConstPointer();
7184 int nbOfCells=getNumberOfCells();
7185 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7186 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7187 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7189 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7190 types.push_back(curType);
7191 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7193 DataArrayInt *ret=DataArrayInt::New();
7194 ret->alloc(nbOfCells,1);
7195 int *retPtr=ret->getPointer();
7196 std::fill(retPtr,retPtr+nbOfCells,-1);
7198 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7200 for(const int *i=connI;i!=connI+nbOfCells;i++)
7201 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7202 retPtr[std::distance(connI,i)]=newCellId++;
7204 renumberCells(retPtr,false);
7209 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7210 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7211 * This method makes asumption that connectivity is correctly set before calling.
7213 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7215 checkConnectivityFullyDefined();
7216 const int *conn=_nodal_connec->getConstPointer();
7217 const int *connI=_nodal_connec_index->getConstPointer();
7218 int nbOfCells=getNumberOfCells();
7219 std::vector<MEDCouplingUMesh *> ret;
7220 for(const int *i=connI;i!=connI+nbOfCells;)
7222 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7223 int beginCellId=(int)std::distance(connI,i);
7224 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7225 int endCellId=(int)std::distance(connI,i);
7226 int sz=endCellId-beginCellId;
7227 int *cells=new int[sz];
7228 for(int j=0;j<sz;j++)
7229 cells[j]=beginCellId+j;
7230 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7238 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7239 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7240 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7242 * \return a newly allocated instance, that the caller must manage.
7243 * \throw If \a this contains more than one geometric type.
7244 * \throw If the nodal connectivity of \a this is not fully defined.
7245 * \throw If the internal data is not coherent.
7247 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7249 checkConnectivityFullyDefined();
7250 if(_types.size()!=1)
7251 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7252 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7253 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7254 ret->setCoords(getCoords());
7255 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7259 retC->setNodalConnectivity(c);
7263 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7265 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7266 DataArrayInt *c=0,*ci=0;
7267 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7269 retD->setNodalConnectivity(cs,cis);
7274 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7276 checkConnectivityFullyDefined();
7277 if(_types.size()!=1)
7278 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7279 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7280 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7283 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7284 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7285 throw INTERP_KERNEL::Exception(oss.str().c_str());
7287 int nbCells=getNumberOfCells();
7289 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7291 int *outPtr=connOut->getPointer();
7292 const int *conn=_nodal_connec->begin();
7293 const int *connI=_nodal_connec_index->begin();
7295 for(int i=0;i<nbCells;i++,connI++)
7297 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7298 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7301 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 << ") !";
7302 throw INTERP_KERNEL::Exception(oss.str().c_str());
7305 return connOut.retn();
7308 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7310 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7311 checkConnectivityFullyDefined();
7312 if(_types.size()!=1)
7313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7314 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7316 throw INTERP_KERNEL::Exception(msg0);
7317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7318 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7319 int *cp(c->getPointer()),*cip(ci->getPointer());
7320 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7322 for(int i=0;i<nbCells;i++,cip++,incip++)
7324 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7325 int delta(stop-strt);
7328 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7329 cp=std::copy(incp+strt,incp+stop,cp);
7331 throw INTERP_KERNEL::Exception(msg0);
7334 throw INTERP_KERNEL::Exception(msg0);
7335 cip[1]=cip[0]+delta;
7337 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7341 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7342 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7343 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7344 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7345 * are not used here to avoid the build of big permutation array.
7347 * \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
7348 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7349 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7350 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7351 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7352 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7353 * \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
7354 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7356 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7357 DataArrayInt *&szOfCellGrpOfSameType,
7358 DataArrayInt *&idInMsOfCellGrpOfSameType)
7360 std::vector<const MEDCouplingUMesh *> ms2;
7361 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7364 (*it)->checkConnectivityFullyDefined();
7368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7369 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7370 int meshDim=ms2[0]->getMeshDimension();
7371 std::vector<const MEDCouplingUMesh *> m1ssm;
7372 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7374 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7375 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7378 ret1->alloc(0,1); ret2->alloc(0,1);
7379 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7381 if(meshDim!=(*it)->getMeshDimension())
7382 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7383 if(refCoo!=(*it)->getCoords())
7384 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7385 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7386 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7387 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7388 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7390 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7391 m1ssmSingleAuto.push_back(singleCell);
7392 m1ssmSingle.push_back(singleCell);
7393 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7397 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7398 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7399 for(std::size_t i=0;i<m1ssm.size();i++)
7400 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7402 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7403 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7408 * This method returns a newly created DataArrayInt instance.
7409 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7411 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7413 checkFullyDefined();
7414 const int *conn=_nodal_connec->getConstPointer();
7415 const int *connIndex=_nodal_connec_index->getConstPointer();
7416 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7417 for(const int *w=begin;w!=end;w++)
7418 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7419 ret->pushBackSilent(*w);
7424 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7425 * are in [0:getNumberOfCells())
7427 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7429 checkFullyDefined();
7430 const int *conn=_nodal_connec->getConstPointer();
7431 const int *connI=_nodal_connec_index->getConstPointer();
7432 int nbOfCells=getNumberOfCells();
7433 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7434 int *tmp=new int[nbOfCells];
7435 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7438 for(const int *i=connI;i!=connI+nbOfCells;i++)
7439 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7440 tmp[std::distance(connI,i)]=j++;
7442 DataArrayInt *ret=DataArrayInt::New();
7443 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7444 ret->copyStringInfoFrom(*da);
7445 int *retPtr=ret->getPointer();
7446 const int *daPtr=da->getConstPointer();
7447 int nbOfElems=da->getNbOfElems();
7448 for(int k=0;k<nbOfElems;k++)
7449 retPtr[k]=tmp[daPtr[k]];
7455 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7456 * This method \b works \b for mesh sorted by type.
7457 * cells whose ids is in 'idsPerGeoType' array.
7458 * This method conserves coords and name of mesh.
7460 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7462 std::vector<int> code=getDistributionOfTypes();
7463 std::size_t nOfTypesInThis=code.size()/3;
7464 int sz=0,szOfType=0;
7465 for(std::size_t i=0;i<nOfTypesInThis;i++)
7470 szOfType=code[3*i+1];
7472 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7473 if(*work<0 || *work>=szOfType)
7475 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7476 oss << ". It should be in [0," << szOfType << ") !";
7477 throw INTERP_KERNEL::Exception(oss.str().c_str());
7479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7480 int *idsPtr=idsTokeep->getPointer();
7482 for(std::size_t i=0;i<nOfTypesInThis;i++)
7485 for(int j=0;j<code[3*i+1];j++)
7488 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7489 offset+=code[3*i+1];
7491 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7492 ret->copyTinyInfoFrom(this);
7497 * This method returns a vector of size 'this->getNumberOfCells()'.
7498 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7500 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7502 int ncell=getNumberOfCells();
7503 std::vector<bool> ret(ncell);
7504 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7505 const int *c=getNodalConnectivity()->getConstPointer();
7506 for(int i=0;i<ncell;i++)
7508 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7509 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7510 ret[i]=cm.isQuadratic();
7516 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7518 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7520 if(other->getType()!=UNSTRUCTURED)
7521 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7522 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7523 return MergeUMeshes(this,otherC);
7527 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7528 * computed by averaging coordinates of cell nodes, so this method is not a right
7529 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7530 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7531 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7532 * components. The caller is to delete this array using decrRef() as it is
7534 * \throw If the coordinates array is not set.
7535 * \throw If the nodal connectivity of cells is not defined.
7536 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7538 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7540 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7541 int spaceDim=getSpaceDimension();
7542 int nbOfCells=getNumberOfCells();
7543 ret->alloc(nbOfCells,spaceDim);
7544 ret->copyStringInfoFrom(*getCoords());
7545 double *ptToFill=ret->getPointer();
7546 const int *nodal=_nodal_connec->getConstPointer();
7547 const int *nodalI=_nodal_connec_index->getConstPointer();
7548 const double *coor=_coords->getConstPointer();
7549 for(int i=0;i<nbOfCells;i++)
7551 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7552 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7559 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7560 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7562 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7563 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7565 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7566 * \throw If \a this is not fully defined (coordinates and connectivity)
7567 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7569 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7571 checkFullyDefined();
7572 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7573 int spaceDim=getSpaceDimension();
7574 int nbOfCells=getNumberOfCells();
7575 int nbOfNodes=getNumberOfNodes();
7576 ret->alloc(nbOfCells,spaceDim);
7577 double *ptToFill=ret->getPointer();
7578 const int *nodal=_nodal_connec->getConstPointer();
7579 const int *nodalI=_nodal_connec_index->getConstPointer();
7580 const double *coor=_coords->getConstPointer();
7581 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7583 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7584 std::fill(ptToFill,ptToFill+spaceDim,0.);
7585 if(type!=INTERP_KERNEL::NORM_POLYHED)
7587 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7589 if(*conn>=0 && *conn<nbOfNodes)
7590 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7593 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7594 throw INTERP_KERNEL::Exception(oss.str().c_str());
7597 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7598 if(nbOfNodesInCell>0)
7599 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7602 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7603 throw INTERP_KERNEL::Exception(oss.str().c_str());
7608 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7610 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7612 if(*it>=0 && *it<nbOfNodes)
7613 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7616 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7617 throw INTERP_KERNEL::Exception(oss.str().c_str());
7621 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7624 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7625 throw INTERP_KERNEL::Exception(oss.str().c_str());
7633 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7634 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7635 * are specified via an array of cell ids.
7636 * \warning Validity of the specified cell ids is not checked!
7637 * Valid range is [ 0, \a this->getNumberOfCells() ).
7638 * \param [in] begin - an array of cell ids of interest.
7639 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7640 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7641 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7642 * caller is to delete this array using decrRef() as it is no more needed.
7643 * \throw If the coordinates array is not set.
7644 * \throw If the nodal connectivity of cells is not defined.
7646 * \if ENABLE_EXAMPLES
7647 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7648 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7651 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7653 DataArrayDouble *ret=DataArrayDouble::New();
7654 int spaceDim=getSpaceDimension();
7655 int nbOfTuple=(int)std::distance(begin,end);
7656 ret->alloc(nbOfTuple,spaceDim);
7657 double *ptToFill=ret->getPointer();
7658 double *tmp=new double[spaceDim];
7659 const int *nodal=_nodal_connec->getConstPointer();
7660 const int *nodalI=_nodal_connec_index->getConstPointer();
7661 const double *coor=_coords->getConstPointer();
7662 for(const int *w=begin;w!=end;w++)
7664 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7665 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7673 * 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".
7674 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7675 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7676 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7677 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7679 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7680 * \throw If spaceDim!=3 or meshDim!=2.
7681 * \throw If connectivity of \a this is invalid.
7682 * \throw If connectivity of a cell in \a this points to an invalid node.
7684 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7686 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7687 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7688 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7689 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7690 ret->alloc(nbOfCells,4);
7691 double *retPtr(ret->getPointer());
7692 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7693 const double *coor(_coords->begin());
7694 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7696 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7697 if(nodalI[1]-nodalI[0]>=3)
7699 for(int j=0;j<3;j++)
7701 int nodeId(nodal[nodalI[0]+1+j]);
7702 if(nodeId>=0 && nodeId<nbOfNodes)
7703 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7706 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7707 throw INTERP_KERNEL::Exception(oss.str().c_str());
7713 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7714 throw INTERP_KERNEL::Exception(oss.str().c_str());
7716 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7717 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7723 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7726 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7729 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7730 da->checkAllocated();
7731 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7733 int nbOfTuples=da->getNumberOfTuples();
7734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7735 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7736 c->alloc(2*nbOfTuples,1);
7737 cI->alloc(nbOfTuples+1,1);
7738 int *cp=c->getPointer();
7739 int *cip=cI->getPointer();
7741 for(int i=0;i<nbOfTuples;i++)
7743 *cp++=INTERP_KERNEL::NORM_POINT1;
7747 ret->setConnectivity(c,cI,true);
7751 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7752 * Cells and nodes of
7753 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7754 * \param [in] mesh1 - the first mesh.
7755 * \param [in] mesh2 - the second mesh.
7756 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7757 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7758 * is no more needed.
7759 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7760 * \throw If the coordinates array is not set in none of the meshes.
7761 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7762 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7764 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7766 std::vector<const MEDCouplingUMesh *> tmp(2);
7767 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7768 return MergeUMeshes(tmp);
7772 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7773 * Cells and nodes of
7774 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7775 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7776 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7777 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7778 * is no more needed.
7779 * \throw If \a a.size() == 0.
7780 * \throw If \a a[ *i* ] == NULL.
7781 * \throw If the coordinates array is not set in none of the meshes.
7782 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7783 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7785 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7787 std::size_t sz=a.size();
7789 return MergeUMeshesLL(a);
7790 for(std::size_t ii=0;ii<sz;ii++)
7793 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7794 throw INTERP_KERNEL::Exception(oss.str().c_str());
7796 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7797 std::vector< const MEDCouplingUMesh * > aa(sz);
7799 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7801 const MEDCouplingUMesh *cur=a[i];
7802 const DataArrayDouble *coo=cur->getCoords();
7804 spaceDim=coo->getNumberOfComponents();
7807 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7808 for(std::size_t i=0;i<sz;i++)
7810 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7813 return MergeUMeshesLL(aa);
7818 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7821 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7822 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7823 int meshDim=(*it)->getMeshDimension();
7824 int nbOfCells=(*it)->getNumberOfCells();
7825 int meshLgth=(*it++)->getMeshLength();
7826 for(;it!=a.end();it++)
7828 if(meshDim!=(*it)->getMeshDimension())
7829 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7830 nbOfCells+=(*it)->getNumberOfCells();
7831 meshLgth+=(*it)->getMeshLength();
7833 std::vector<const MEDCouplingPointSet *> aps(a.size());
7834 std::copy(a.begin(),a.end(),aps.begin());
7835 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7836 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7837 ret->setCoords(pts);
7838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7839 c->alloc(meshLgth,1);
7840 int *cPtr=c->getPointer();
7841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7842 cI->alloc(nbOfCells+1,1);
7843 int *cIPtr=cI->getPointer();
7847 for(it=a.begin();it!=a.end();it++)
7849 int curNbOfCell=(*it)->getNumberOfCells();
7850 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7851 const int *curC=(*it)->_nodal_connec->getConstPointer();
7852 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7853 for(int j=0;j<curNbOfCell;j++)
7855 const int *src=curC+curCI[j];
7857 for(;src!=curC+curCI[j+1];src++,cPtr++)
7865 offset+=curCI[curNbOfCell];
7866 offset2+=(*it)->getNumberOfNodes();
7869 ret->setConnectivity(c,cI,true);
7876 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7877 * dimension and sharing the node coordinates array.
7878 * All cells of the first mesh precede all cells of the second mesh
7879 * within the result mesh.
7880 * \param [in] mesh1 - the first mesh.
7881 * \param [in] mesh2 - the second mesh.
7882 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7883 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7884 * is no more needed.
7885 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7886 * \throw If the meshes do not share the node coordinates array.
7887 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7888 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7890 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7892 std::vector<const MEDCouplingUMesh *> tmp(2);
7893 tmp[0]=mesh1; tmp[1]=mesh2;
7894 return MergeUMeshesOnSameCoords(tmp);
7898 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7899 * dimension and sharing the node coordinates array.
7900 * All cells of the *i*-th mesh precede all cells of the
7901 * (*i*+1)-th mesh within the result mesh.
7902 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7903 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7904 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7905 * is no more needed.
7906 * \throw If \a a.size() == 0.
7907 * \throw If \a a[ *i* ] == NULL.
7908 * \throw If the meshes do not share the node coordinates array.
7909 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7910 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7912 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7915 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7916 for(std::size_t ii=0;ii<meshes.size();ii++)
7919 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7920 throw INTERP_KERNEL::Exception(oss.str().c_str());
7922 const DataArrayDouble *coords=meshes.front()->getCoords();
7923 int meshDim=meshes.front()->getMeshDimension();
7924 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7926 int meshIndexLgth=0;
7927 for(;iter!=meshes.end();iter++)
7929 if(coords!=(*iter)->getCoords())
7930 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7931 if(meshDim!=(*iter)->getMeshDimension())
7932 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7933 meshLgth+=(*iter)->getMeshLength();
7934 meshIndexLgth+=(*iter)->getNumberOfCells();
7936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7937 nodal->alloc(meshLgth,1);
7938 int *nodalPtr=nodal->getPointer();
7939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7940 nodalIndex->alloc(meshIndexLgth+1,1);
7941 int *nodalIndexPtr=nodalIndex->getPointer();
7943 for(iter=meshes.begin();iter!=meshes.end();iter++)
7945 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7946 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7947 int nbOfCells=(*iter)->getNumberOfCells();
7948 int meshLgth2=(*iter)->getMeshLength();
7949 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7950 if(iter!=meshes.begin())
7951 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7953 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7956 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7957 ret->setName("merge");
7958 ret->setMeshDimension(meshDim);
7959 ret->setConnectivity(nodal,nodalIndex,true);
7960 ret->setCoords(coords);
7965 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7966 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7967 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7968 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7969 * New" mode are returned for each input mesh.
7970 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7971 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7972 * valid values [0,1,2], see zipConnectivityTraducer().
7973 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7974 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7975 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7977 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7978 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7979 * is no more needed.
7980 * \throw If \a meshes.size() == 0.
7981 * \throw If \a meshes[ *i* ] == NULL.
7982 * \throw If the meshes do not share the node coordinates array.
7983 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7984 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7985 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7986 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7988 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7990 //All checks are delegated to MergeUMeshesOnSameCoords
7991 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7992 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7993 corr.resize(meshes.size());
7994 std::size_t nbOfMeshes=meshes.size();
7996 const int *o2nPtr=o2n->getConstPointer();
7997 for(std::size_t i=0;i<nbOfMeshes;i++)
7999 DataArrayInt *tmp=DataArrayInt::New();
8000 int curNbOfCells=meshes[i]->getNumberOfCells();
8001 tmp->alloc(curNbOfCells,1);
8002 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8003 offset+=curNbOfCells;
8004 tmp->setName(meshes[i]->getName());
8011 * Makes all given meshes share the nodal connectivity array. The common connectivity
8012 * array is created by concatenating the connectivity arrays of all given meshes. All
8013 * the given meshes must be of the same space dimension but dimension of cells **can
8014 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8015 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8016 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8017 * \param [in,out] meshes - a vector of meshes to update.
8018 * \throw If any of \a meshes is NULL.
8019 * \throw If the coordinates array is not set in any of \a meshes.
8020 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8021 * \throw If \a meshes are of different space dimension.
8023 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8025 std::size_t sz=meshes.size();
8028 std::vector< const DataArrayDouble * > coords(meshes.size());
8029 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8030 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8034 (*it)->checkConnectivityFullyDefined();
8035 const DataArrayDouble *coo=(*it)->getCoords();
8040 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8041 oss << " has no coordinate array defined !";
8042 throw INTERP_KERNEL::Exception(oss.str().c_str());
8047 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8048 oss << " is null !";
8049 throw INTERP_KERNEL::Exception(oss.str().c_str());
8052 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8053 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8054 int offset=(*it)->getNumberOfNodes();
8055 (*it++)->setCoords(res);
8056 for(;it!=meshes.end();it++)
8058 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8059 (*it)->setCoords(res);
8060 (*it)->shiftNodeNumbersInConn(offset);
8061 offset+=oldNumberOfNodes;
8066 * Merges nodes coincident with a given precision within all given meshes that share
8067 * the nodal connectivity array. The given meshes **can be of different** mesh
8068 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8069 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8070 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8071 * \param [in,out] meshes - a vector of meshes to update.
8072 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8073 * \throw If any of \a meshes is NULL.
8074 * \throw If the \a meshes do not share the same node coordinates array.
8075 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8077 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8081 std::set<const DataArrayDouble *> s;
8082 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8085 s.insert((*it)->getCoords());
8088 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 !";
8089 throw INTERP_KERNEL::Exception(oss.str().c_str());
8094 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 !";
8095 throw INTERP_KERNEL::Exception(oss.str().c_str());
8097 const DataArrayDouble *coo=*(s.begin());
8101 DataArrayInt *comm,*commI;
8102 coo->findCommonTuples(eps,-1,comm,commI);
8103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8104 int oldNbOfNodes=coo->getNumberOfTuples();
8106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8107 if(oldNbOfNodes==newNbOfNodes)
8109 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8110 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8112 (*it)->renumberNodesInConn(o2n->getConstPointer());
8113 (*it)->setCoords(newCoords);
8118 * 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.
8119 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8120 * \param isQuad specifies the policy of connectivity.
8121 * @ret in/out parameter in which the result will be append
8123 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8125 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8126 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8127 ret.push_back(cm.getExtrudedType());
8128 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8131 case INTERP_KERNEL::NORM_POINT1:
8133 ret.push_back(connBg[1]);
8134 ret.push_back(connBg[1]+nbOfNodesPerLev);
8137 case INTERP_KERNEL::NORM_SEG2:
8139 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8140 ret.insert(ret.end(),conn,conn+4);
8143 case INTERP_KERNEL::NORM_SEG3:
8145 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8146 ret.insert(ret.end(),conn,conn+8);
8149 case INTERP_KERNEL::NORM_QUAD4:
8151 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8152 ret.insert(ret.end(),conn,conn+8);
8155 case INTERP_KERNEL::NORM_TRI3:
8157 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8158 ret.insert(ret.end(),conn,conn+6);
8161 case INTERP_KERNEL::NORM_TRI6:
8163 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,
8164 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8165 ret.insert(ret.end(),conn,conn+15);
8168 case INTERP_KERNEL::NORM_QUAD8:
8171 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8172 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8173 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8175 ret.insert(ret.end(),conn,conn+20);
8178 case INTERP_KERNEL::NORM_POLYGON:
8180 std::back_insert_iterator< std::vector<int> > ii(ret);
8181 std::copy(connBg+1,connEnd,ii);
8183 std::reverse_iterator<const int *> rConnBg(connEnd);
8184 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8185 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8186 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8187 for(std::size_t i=0;i<nbOfRadFaces;i++)
8190 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8191 std::copy(conn,conn+4,ii);
8196 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8201 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8203 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8206 double v[3]={0.,0.,0.};
8207 std::size_t sz=std::distance(begin,end);
8212 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];
8213 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8214 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8216 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8218 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8219 // SEG3 forming a circle):
8220 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8222 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8223 for(std::size_t j=0;j<sz;j++)
8225 if (j%2) // current point i is quadratic, next point i+1 is standard
8228 ip1 = (j+1)%sz; // ip1 = "i+1"
8230 else // current point i is standard, next point i+1 is quadratic
8235 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8236 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8237 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8239 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8245 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8247 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8249 std::vector<std::pair<int,int> > edges;
8250 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8251 const int *bgFace=begin;
8252 for(std::size_t i=0;i<nbOfFaces;i++)
8254 const int *endFace=std::find(bgFace+1,end,-1);
8255 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8256 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8258 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8259 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8261 edges.push_back(p1);
8265 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8269 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8271 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8273 double vec0[3],vec1[3];
8274 std::size_t sz=std::distance(begin,end);
8276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8277 int nbOfNodes=(int)sz/2;
8278 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8279 const double *pt0=coords+3*begin[0];
8280 const double *pt1=coords+3*begin[nbOfNodes];
8281 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8282 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8285 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8287 std::size_t sz=std::distance(begin,end);
8288 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8289 std::size_t nbOfNodes(sz/2);
8290 std::copy(begin,end,(int *)tmp);
8291 for(std::size_t j=1;j<nbOfNodes;j++)
8293 begin[j]=tmp[nbOfNodes-j];
8294 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8298 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8300 std::size_t sz=std::distance(begin,end);
8302 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8303 double vec0[3],vec1[3];
8304 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8305 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];
8306 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;
8309 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8311 std::size_t sz=std::distance(begin,end);
8313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8315 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8316 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8317 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8321 * 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 )
8322 * 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
8325 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8326 * \param [in] coords the coordinates with nb of components exactly equal to 3
8327 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8328 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8329 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8331 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8333 int nbFaces=std::count(begin+1,end,-1)+1;
8334 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8335 double *vPtr=v->getPointer();
8336 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8337 double *pPtr=p->getPointer();
8338 const int *stFaceConn=begin+1;
8339 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8341 const int *endFaceConn=std::find(stFaceConn,end,-1);
8342 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8343 stFaceConn=endFaceConn+1;
8345 pPtr=p->getPointer(); vPtr=v->getPointer();
8346 DataArrayInt *comm1=0,*commI1=0;
8347 v->findCommonTuples(eps,-1,comm1,commI1);
8348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8349 const int *comm1Ptr=comm1->getConstPointer();
8350 const int *commI1Ptr=commI1->getConstPointer();
8351 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8352 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8354 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8355 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8356 mm->finishInsertingCells();
8358 for(int i=0;i<nbOfGrps1;i++)
8360 int vecId=comm1Ptr[commI1Ptr[i]];
8361 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8362 DataArrayInt *comm2=0,*commI2=0;
8363 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8365 const int *comm2Ptr=comm2->getConstPointer();
8366 const int *commI2Ptr=commI2->getConstPointer();
8367 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8368 for(int j=0;j<nbOfGrps2;j++)
8370 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8372 res->insertAtTheEnd(begin,end);
8373 res->pushBackSilent(-1);
8377 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8379 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8380 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8381 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8382 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8385 const int *idsNodePtr=idsNode->getConstPointer();
8386 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];
8387 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8388 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8389 if(std::abs(norm)>eps)
8391 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8392 mm3->rotate(center,vec,angle);
8394 mm3->changeSpaceDimension(2);
8395 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8396 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8397 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8398 int nbOfCells=mm4->getNumberOfCells();
8399 for(int k=0;k<nbOfCells;k++)
8402 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8403 res->pushBackSilent(idsNodePtr[*work]);
8404 res->pushBackSilent(-1);
8409 res->popBackSilent();
8413 * 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
8414 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8416 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8417 * \param [in] coords coordinates expected to have 3 components.
8418 * \param [in] begin start of the nodal connectivity of the face.
8419 * \param [in] end end of the nodal connectivity (excluded) of the face.
8420 * \param [out] v the normalized vector of size 3
8421 * \param [out] p the pos of plane
8423 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8425 std::size_t nbPoints=std::distance(begin,end);
8427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8428 double vec[3]={0.,0.,0.};
8430 bool refFound=false;
8431 for(;j<nbPoints-1 && !refFound;j++)
8433 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8434 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8435 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8436 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8440 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8443 for(std::size_t i=j;i<nbPoints-1;i++)
8446 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8447 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8448 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8449 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8452 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8453 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];
8454 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8457 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8458 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8462 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8466 * This method tries to obtain a well oriented polyhedron.
8467 * If the algorithm fails, an exception will be thrown.
8469 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8471 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8472 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8473 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8475 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8476 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8477 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8479 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8482 std::size_t smthChanged=0;
8483 for(std::size_t i=0;i<nbOfFaces;i++)
8485 endFace=std::find(bgFace+1,end,-1);
8486 nbOfEdgesInFace=std::distance(bgFace,endFace);
8490 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8492 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8493 std::pair<int,int> p2(p1.second,p1.first);
8494 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8495 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8496 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8501 std::reverse(bgFace+1,endFace);
8502 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8504 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8505 std::pair<int,int> p2(p1.second,p1.first);
8506 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8507 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8508 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8509 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8510 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8511 if(it!=edgesOK.end())
8514 edgesFinished.push_back(p1);
8517 edgesOK.push_back(p1);
8524 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8526 if(!edgesOK.empty())
8527 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8528 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8529 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8531 for(std::size_t i=0;i<nbOfFaces;i++)
8533 endFace=std::find(bgFace+1,end,-1);
8534 std::reverse(bgFace+1,endFace);
8540 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8542 int nbOfNodesExpected(skin->getNumberOfNodes());
8543 const int *n2oPtr(n2o->getConstPointer());
8544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8545 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8546 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8547 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8548 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8549 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8550 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8551 if(nbOfNodesExpected<1)
8553 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8554 *work++=n2oPtr[prevNode];
8555 for(int i=1;i<nbOfNodesExpected;i++)
8557 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8559 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8560 conn.erase(prevNode);
8563 int curNode(*(conn.begin()));
8564 *work++=n2oPtr[curNode];
8565 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8566 shar.erase(prevCell);
8569 prevCell=*(shar.begin());
8573 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8584 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8586 int nbOfNodesExpected(skin->getNumberOfNodes());
8587 int nbOfTurn(nbOfNodesExpected/2);
8588 const int *n2oPtr(n2o->getConstPointer());
8589 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8590 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8591 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8592 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8593 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8594 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8595 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8596 if(nbOfNodesExpected<1)
8598 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8599 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8600 for(int i=1;i<nbOfTurn;i++)
8602 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8604 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8605 conn.erase(prevNode);
8608 int curNode(*(conn.begin()));
8609 *work=n2oPtr[curNode];
8610 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8611 shar.erase(prevCell);
8614 int curCell(*(shar.begin()));
8615 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8624 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8633 * This method makes the assumption spacedimension == meshdimension == 2.
8634 * This method works only for linear cells.
8636 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8638 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8640 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8641 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8642 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8643 int oldNbOfNodes(skin->getNumberOfNodes());
8644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8645 int nbOfNodesExpected(skin->getNumberOfNodes());
8646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8647 int nbCells(skin->getNumberOfCells());
8648 if(nbCells==nbOfNodesExpected)
8649 return buildUnionOf2DMeshLinear(skin,n2o);
8650 else if(2*nbCells==nbOfNodesExpected)
8651 return buildUnionOf2DMeshQuadratic(skin,n2o);
8653 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8657 * This method makes the assumption spacedimension == meshdimension == 3.
8658 * This method works only for linear cells.
8660 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8662 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8664 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8665 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8666 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8667 const int *conn=m->getNodalConnectivity()->getConstPointer();
8668 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8669 int nbOfCells=m->getNumberOfCells();
8670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8671 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8674 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8675 for(int i=1;i<nbOfCells;i++)
8678 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8684 * \brief Creates a graph of cell neighbors
8685 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8686 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8688 * - index: 0 3 5 6 6
8689 * - value: 1 2 3 2 3 3
8690 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8691 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8693 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8695 checkConnectivityFullyDefined();
8697 int meshDim = this->getMeshDimension();
8698 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8699 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8700 this->getReverseNodalConnectivity(revConn,indexr);
8701 const int* indexr_ptr=indexr->getConstPointer();
8702 const int* revConn_ptr=revConn->getConstPointer();
8704 const ParaMEDMEM::DataArrayInt* index;
8705 const ParaMEDMEM::DataArrayInt* conn;
8706 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8707 index=this->getNodalConnectivityIndex();
8708 int nbCells=this->getNumberOfCells();
8709 const int* index_ptr=index->getConstPointer();
8710 const int* conn_ptr=conn->getConstPointer();
8712 //creating graph arcs (cell to cell relations)
8713 //arcs are stored in terms of (index,value) notation
8716 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8717 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8719 //warning here one node have less than or equal effective number of cell with it
8720 //but cell could have more than effective nodes
8721 //because other equals nodes in other domain (with other global inode)
8722 std::vector <int> cell2cell_index(nbCells+1,0);
8723 std::vector <int> cell2cell;
8724 cell2cell.reserve(3*nbCells);
8726 for (int icell=0; icell<nbCells;icell++)
8728 std::map<int,int > counter;
8729 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8731 int inode=conn_ptr[iconn];
8732 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8734 int icell2=revConn_ptr[iconnr];
8735 std::map<int,int>::iterator iter=counter.find(icell2);
8736 if (iter!=counter.end()) (iter->second)++;
8737 else counter.insert(std::make_pair(icell2,1));
8740 for (std::map<int,int>::const_iterator iter=counter.begin();
8741 iter!=counter.end(); iter++)
8742 if (iter->second >= meshDim)
8744 cell2cell_index[icell+1]++;
8745 cell2cell.push_back(iter->first);
8750 cell2cell_index[0]=0;
8751 for (int icell=0; icell<nbCells;icell++)
8752 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8754 //filling up index and value to create skylinearray structure
8755 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8760 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8761 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8763 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8767 for(int i=0;i<nbOfNodesInCell;i++)
8768 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8769 else if(spaceDim==2)
8771 for(int i=0;i<nbOfNodesInCell;i++)
8773 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8778 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8781 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8783 int nbOfCells=getNumberOfCells();
8785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8786 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};
8787 ofs << " <" << getVTKDataSetType() << ">\n";
8788 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8789 ofs << " <PointData>\n" << pointData << std::endl;
8790 ofs << " </PointData>\n";
8791 ofs << " <CellData>\n" << cellData << std::endl;
8792 ofs << " </CellData>\n";
8793 ofs << " <Points>\n";
8794 if(getSpaceDimension()==3)
8795 _coords->writeVTK(ofs,8,"Points",byteData);
8798 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8799 coo->writeVTK(ofs,8,"Points",byteData);
8801 ofs << " </Points>\n";
8802 ofs << " <Cells>\n";
8803 const int *cPtr=_nodal_connec->getConstPointer();
8804 const int *cIPtr=_nodal_connec_index->getConstPointer();
8805 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8806 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8809 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8810 int szFaceOffsets=0,szConn=0;
8811 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8814 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8817 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8818 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8822 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8823 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8824 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8825 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8826 w4=std::copy(c.begin(),c.end(),w4);
8829 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8830 types->writeVTK(ofs,8,"UInt8","types",byteData);
8831 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8832 if(szFaceOffsets!=0)
8833 {//presence of Polyhedra
8834 connectivity->reAlloc(szConn);
8835 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8837 w1=faces->getPointer();
8838 for(int i=0;i<nbOfCells;i++)
8839 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8841 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8843 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8844 for(int j=0;j<nbFaces;j++)
8846 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8847 *w1++=(int)std::distance(w6,w5);
8848 w1=std::copy(w6,w5,w1);
8852 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8854 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8855 ofs << " </Cells>\n";
8856 ofs << " </Piece>\n";
8857 ofs << " </" << getVTKDataSetType() << ">\n";
8860 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8862 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8864 { stream << " Not set !"; return ; }
8865 stream << " Mesh dimension : " << _mesh_dim << ".";
8869 { stream << " No coordinates set !"; return ; }
8870 if(!_coords->isAllocated())
8871 { stream << " Coordinates set but not allocated !"; return ; }
8872 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8873 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8874 if(!_nodal_connec_index)
8875 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8876 if(!_nodal_connec_index->isAllocated())
8877 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8878 int lgth=_nodal_connec_index->getNumberOfTuples();
8879 int cpt=_nodal_connec_index->getNumberOfComponents();
8880 if(cpt!=1 || lgth<1)
8882 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8885 std::string MEDCouplingUMesh::getVTKDataSetType() const
8887 return std::string("UnstructuredGrid");
8890 std::string MEDCouplingUMesh::getVTKFileExtension() const
8892 return std::string("vtu");
8896 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8897 * returns a result mesh constituted by polygons.
8898 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8899 * all nodes from m2.
8900 * The meshes should be in 2D space. In
8901 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8903 * \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
8904 * 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)
8905 * \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
8906 * 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)
8907 * \param [in] eps - precision used to detect coincident mesh entities.
8908 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8909 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8910 * this array using decrRef() as it is no more needed.
8911 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8912 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8913 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8914 * any cell of \a m2. The caller is to delete this array using decrRef() as
8915 * it is no more needed.
8916 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8917 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8918 * is no more needed.
8919 * \throw If the coordinates array is not set in any of the meshes.
8920 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8921 * \throw If any of the meshes is not a 2D mesh in 2D space.
8923 * \sa conformize2D, mergeNodes
8925 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8926 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8929 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8930 m1->checkFullyDefined();
8931 m2->checkFullyDefined();
8932 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8933 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8935 // Step 1: compute all edge intersections (new nodes)
8936 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8937 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8938 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8939 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8940 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8941 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8942 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8943 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8944 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8947 // Step 2: re-order newly created nodes according to the ordering found in m2
8948 std::vector< std::vector<int> > intersectEdge2;
8949 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8950 subDiv2.clear(); dd5=0; dd6=0;
8953 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8954 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8955 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8956 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8958 // Step 4: Prepare final result:
8959 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8960 addCooDa->alloc((int)(addCoo.size())/2,2);
8961 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8962 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8963 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8964 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8965 std::vector<const DataArrayDouble *> coordss(4);
8966 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8967 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8968 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8971 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8973 ret->setConnectivity(conn,connI,true);
8974 ret->setCoords(coo);
8975 cellNb1=c1.retn(); cellNb2=c2.retn();
8981 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8983 if(candidates.empty())
8985 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8987 const std::vector<int>& pool(intersectEdge1[*it]);
8988 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8989 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8994 tmp[0]=stop; tmp[1]=start;
8995 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9004 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,
9005 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9007 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9008 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9009 int nCells(mesh1D->getNumberOfCells());
9010 if(nCells!=(int)intersectEdge2.size())
9011 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9012 const DataArrayDouble *coo2(mesh1D->getCoords());
9013 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9014 const double *coo2Ptr(coo2->begin());
9015 int offset1(coords1->getNumberOfTuples());
9016 int offset2(offset1+coo2->getNumberOfTuples());
9017 int offset3(offset2+addCoo.size()/2);
9018 std::vector<double> addCooQuad;
9019 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9020 int tmp[4],cicnt(0),kk(0);
9021 for(int i=0;i<nCells;i++)
9023 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9024 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9025 const std::vector<int>& subEdges(intersectEdge2[i]);
9026 int nbSubEdge(subEdges.size()/2);
9027 for(int j=0;j<nbSubEdge;j++,kk++)
9029 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));
9030 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9031 INTERP_KERNEL::Edge *e2Ptr(e2);
9032 std::map<int,int>::const_iterator itm;
9033 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9035 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9036 itm=mergedNodes.find(subEdges[2*j]);
9037 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9038 itm=mergedNodes.find(subEdges[2*j+1]);
9039 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9040 tmp[3]=offset3+(int)addCooQuad.size()/2;
9042 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9044 cOut->insertAtTheEnd(tmp,tmp+4);
9045 ciOut->pushBackSilent(cicnt);
9049 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9050 itm=mergedNodes.find(subEdges[2*j]);
9051 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9052 itm=mergedNodes.find(subEdges[2*j+1]);
9053 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9055 cOut->insertAtTheEnd(tmp,tmp+3);
9056 ciOut->pushBackSilent(cicnt);
9059 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9061 idsInRetColinear->pushBackSilent(kk);
9062 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9067 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9068 ret->setConnectivity(cOut,ciOut,true);
9069 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9070 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9071 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9072 std::vector<const DataArrayDouble *> coordss(4);
9073 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9074 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9075 ret->setCoords(arr);
9079 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9081 std::vector<int> allEdges;
9082 for(const int *it2(descBg);it2!=descEnd;it2++)
9084 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9086 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9088 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9090 std::size_t nb(allEdges.size());
9092 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9093 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9094 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9095 ret->setCoords(coords);
9096 ret->allocateCells(1);
9097 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9098 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9099 connOut[kk]=allEdges[2*kk];
9100 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9104 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9106 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9107 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9109 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9110 if(sz!=std::distance(descBg,descEnd))
9111 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9112 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9113 std::vector<int> allEdges,centers;
9114 const double *coordsPtr(coords->begin());
9115 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9116 int offset(coords->getNumberOfTuples());
9117 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9119 INTERP_KERNEL::NormalizedCellType typeOfSon;
9120 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9121 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9123 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9125 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9127 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9129 {//the current edge has been subsplit -> create corresponding centers.
9130 std::size_t nbOfCentersToAppend(edge1.size()/2);
9131 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9132 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9133 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9134 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9137 const double *aa(coordsPtr+2*(*it3++));
9138 const double *bb(coordsPtr+2*(*it3++));
9139 ee->getMiddleOfPoints(aa,bb,tmpp);
9140 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9141 centers.push_back(offset+k);
9145 std::size_t nb(allEdges.size());
9147 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9148 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9149 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9151 ret->setCoords(coords);
9154 addCoo->rearrange(2);
9155 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9156 ret->setCoords(addCoo);
9158 ret->allocateCells(1);
9159 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9160 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9161 connOut[kk]=allEdges[2*kk];
9162 connOut.insert(connOut.end(),centers.begin(),centers.end());
9163 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9168 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9171 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9173 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9175 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9176 if(!cm.isQuadratic())
9177 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9179 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9182 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9185 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9187 const INTERP_KERNEL::Edge *ee(*it);
9188 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9192 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9195 const double *coo(mesh2D->getCoords()->begin());
9196 std::size_t sz(conn.size());
9197 std::vector<double> addCoo;
9198 std::vector<int> conn2(conn);
9199 int offset(mesh2D->getNumberOfNodes());
9200 for(std::size_t i=0;i<sz;i++)
9203 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9204 addCoo.insert(addCoo.end(),tmp,tmp+2);
9205 conn2.push_back(offset+(int)i);
9207 mesh2D->getCoords()->rearrange(1);
9208 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9209 mesh2D->getCoords()->rearrange(2);
9210 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9215 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9217 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9218 * a set of edges defined in \a splitMesh1D.
9220 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9221 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9223 std::size_t nb(edge1Bis.size()/2);
9224 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9225 int iEnd(splitMesh1D->getNumberOfCells());
9227 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9229 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9230 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9231 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9234 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9235 out0.resize(1); out1.resize(1);
9236 std::vector<int>& connOut(out0[0]);
9237 connOut.resize(nbOfEdgesOf2DCellSplit);
9238 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9239 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9240 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9242 connOut[kk]=edge1Bis[2*kk];
9243 edgesPtr[kk]=edge1BisPtr[2*kk];
9248 // [i,iEnd[ contains the
9249 out0.resize(2); out1.resize(2);
9250 std::vector<int>& connOutLeft(out0[0]);
9251 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9252 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9253 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9254 for(std::size_t k=ii;k<jj+1;k++)
9255 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9256 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9257 for(int ik=0;ik<iEnd;ik++)
9259 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9260 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9263 for(int ik=iEnd-1;ik>=0;ik--)
9264 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9265 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9266 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9267 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9268 for(int ik=0;ik<iEnd;ik++)
9269 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9270 eright.insert(eright.end(),ees.begin(),ees.end());
9282 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9284 std::vector<int> _edges;
9285 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9288 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9290 std::size_t nbe(edges.size());
9291 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9292 for(std::size_t i=0;i<nbe;i++)
9294 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9295 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9297 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9298 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9299 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9305 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9306 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9307 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9308 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9309 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9313 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9314 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9319 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9321 const MEDCouplingUMesh *mesh(_mesh);
9327 { _left++; _right++; return ; }
9330 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9331 if((isLeft && isRight) || (!isLeft && !isRight))
9332 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9343 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9344 if((isLeft && isRight) || (!isLeft && !isRight))
9345 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9360 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9362 const MEDCouplingUMesh *mesh(_mesh);
9365 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9368 {// not fully splitting cell case
9369 if(mesh2D->getNumberOfCells()==1)
9370 {//little optimization. 1 cell no need to find in which cell mesh is !
9371 neighbors[0]=offset; neighbors[1]=offset;
9376 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9377 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9379 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9380 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9385 class VectorOfCellInfo
9388 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9389 std::size_t size() const { return _pool.size(); }
9390 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9391 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);
9392 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9393 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9394 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9395 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9397 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9398 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9399 const CellInfo& get(int pos) const;
9400 CellInfo& get(int pos);
9402 std::vector<CellInfo> _pool;
9403 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9404 std::vector<EdgeInfo> _edge_info;
9407 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9409 _pool[0]._edges=edges;
9410 _pool[0]._edges_ptr=edgesPtr;
9413 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9416 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9419 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9421 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9422 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9423 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9426 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)
9428 get(pos);//to check pos
9429 bool isFast(pos==0 && _pool.size()==1);
9430 std::size_t sz(edges.size());
9431 // dealing with edges
9433 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9435 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9437 std::vector<CellInfo> pool(_pool.size()-1+sz);
9438 for(int i=0;i<pos;i++)
9440 for(std::size_t j=0;j<sz;j++)
9441 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9442 for(int i=pos+1;i<(int)_pool.size();i++)
9443 pool[i+sz-1]=_pool[i];
9447 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9455 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9458 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9462 if(pos<_ze_mesh->getNumberOfCells()-1)
9464 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9467 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9468 for(std::size_t j=0;j<ms2.size();j++)
9470 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9473 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9475 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9478 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9481 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9483 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9485 if((*it).isInMyRange(pos))
9488 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9491 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9493 get(pos);//to check;
9494 if(_edge_info.empty())
9496 std::size_t sz(_edge_info.size()-1);
9497 for(std::size_t i=0;i<sz;i++)
9498 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9501 const CellInfo& VectorOfCellInfo::get(int pos) const
9503 if(pos<0 || pos>=(int)_pool.size())
9504 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9508 CellInfo& VectorOfCellInfo::get(int pos)
9510 if(pos<0 || pos>=(int)_pool.size())
9511 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9517 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9518 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9520 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9522 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9524 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9526 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9527 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9529 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9530 if(nbCellsInSplitMesh1D==0)
9531 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9532 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9533 std::size_t nb(allEdges.size()),jj;
9535 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9536 std::vector<int> edge1Bis(nb*2);
9537 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9538 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9539 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9540 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9541 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9543 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9544 int *idsLeftRightPtr(idsLeftRight->getPointer());
9545 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9546 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9547 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9549 for(;iEnd<nbCellsInSplitMesh1D;)
9551 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9557 if(iEnd<nbCellsInSplitMesh1D)
9560 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9561 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9563 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9564 retTmp->setCoords(splitMesh1D->getCoords());
9565 retTmp->allocateCells();
9567 std::vector< std::vector<int> > out0;
9568 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9570 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9571 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9572 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9573 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9577 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9578 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9579 return pool.getZeMesh().retn();
9582 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9583 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9584 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9586 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9588 std::vector<int> allEdges;
9589 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9590 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9592 int edgeId(std::abs(*it)-1);
9593 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9594 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9595 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9597 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9599 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9600 std::size_t sz(edge1.size());
9601 for(std::size_t cnt=0;cnt<sz;cnt++)
9602 allEdgesPtr.push_back(ee);
9605 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9608 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9610 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9611 {//easy case comparison not
9612 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9614 else if(typ1.isQuadratic() && typ2.isQuadratic())
9616 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9619 if(conn1[2]==conn2[2])
9621 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9622 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9626 {//only one is quadratic
9627 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9630 const double *a(0),*bb(0),*be(0);
9631 if(typ1.isQuadratic())
9633 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9637 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9639 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9640 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9646 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9647 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9649 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9651 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9653 if(candidatesIn2DEnd==candidatesIn2DBg)
9654 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9655 const double *coo(mesh2DSplit->getCoords()->begin());
9656 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9657 return *candidatesIn2DBg;
9658 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9659 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9660 if(cellIdInMesh1DSplitRelative<0)
9661 cur1D->changeOrientationOfCells();
9662 const int *c1D(cur1D->getNodalConnectivity()->begin());
9663 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9664 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9666 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9667 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9668 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9669 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9670 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9671 for(unsigned it2=0;it2<sz;it2++)
9673 INTERP_KERNEL::NormalizedCellType typeOfSon;
9674 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9675 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9676 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9680 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9686 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9687 * 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
9688 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9689 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9691 * \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
9692 * 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)
9693 * \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
9694 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9695 * \param [in] eps - precision used to perform intersections and localization operations.
9696 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9697 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9698 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9699 * 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.
9700 * \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
9701 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9702 * 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.
9704 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9706 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9708 if(!mesh2D || !mesh1D)
9709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9710 mesh2D->checkFullyDefined();
9711 mesh1D->checkFullyDefined();
9712 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9713 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9714 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9715 // Step 1: compute all edge intersections (new nodes)
9716 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9717 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9718 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9719 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9721 // Build desc connectivity
9722 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9724 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9725 std::map<int,int> mergedNodes;
9726 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9727 // use mergeNodes to fix intersectEdge1
9728 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9730 std::size_t n((*it0).size()/2);
9731 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9732 std::map<int,int>::const_iterator it1;
9733 it1=mergedNodes.find(eltStart);
9734 if(it1!=mergedNodes.end())
9735 (*it0)[0]=(*it1).second;
9736 it1=mergedNodes.find(eltEnd);
9737 if(it1!=mergedNodes.end())
9738 (*it0)[2*n-1]=(*it1).second;
9741 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9742 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9743 // Step 2: re-order newly created nodes according to the ordering found in m2
9744 std::vector< std::vector<int> > intersectEdge2;
9745 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9747 // Step 3: compute splitMesh1D
9748 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9750 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9751 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9754 // deal with cells in mesh2D that are not cut but only some of their edges are
9755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9756 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9757 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9758 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
9759 if(!idsInDesc2DToBeRefined->empty())
9761 DataArrayInt *out0(0),*outi0(0);
9762 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9763 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9765 out0s=out0s->buildUnique();
9769 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9770 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9771 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9772 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9775 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9776 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9778 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9779 if((DataArrayInt *)out0s)
9780 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9781 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9782 // OK all is ready to insert in ret2 mesh
9783 if(!untouchedCells->empty())
9784 {// the most easy part, cells in mesh2D not impacted at all
9785 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9786 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9787 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9789 if((DataArrayInt *)out0s)
9790 {// here dealing with cells in out0s but not in cellsToBeModified
9791 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9792 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9793 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9795 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9796 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9798 int offset(ret2->getNumberOfTuples());
9799 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9801 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9802 int kk(0),*ret3ptr(partOfRet3->getPointer());
9803 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9805 int faceId(std::abs(*it)-1);
9806 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9808 int tmp(fewModifiedCells->locateValue(*it2));
9811 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9812 ret3ptr[2*kk]=tmp+offset;
9813 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9814 ret3ptr[2*kk+1]=tmp+offset;
9817 {//the current edge is shared by a 2D cell that will be split just after
9818 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9819 ret3ptr[2*kk]=-(*it2+1);
9820 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9821 ret3ptr[2*kk+1]=-(*it2+1);
9825 m1Desc->setCoords(ret1->getCoords());
9826 ret1NonCol->setCoords(ret1->getCoords());
9827 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9828 if(!outMesh2DSplit.empty())
9830 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9831 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9832 (*itt)->setCoords(da);
9835 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9836 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9839 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9841 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9843 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));
9844 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9845 outMesh2DSplit.push_back(splitOfOneCell);
9846 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9847 ret2->pushBackSilent(*it);
9850 std::size_t nbOfMeshes(outMesh2DSplit.size());
9851 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9852 for(std::size_t i=0;i<nbOfMeshes;i++)
9853 tmp[i]=outMesh2DSplit[i];
9855 ret1->getCoords()->setInfoOnComponents(compNames);
9856 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9857 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9860 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9862 int old2DCellId(-ret3->getIJ(*it,0)-1);
9863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9864 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
9866 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9869 splitMesh1D=ret1.retn();
9870 splitMesh2D=ret2D.retn();
9871 cellIdInMesh2D=ret2.retn();
9872 cellIdInMesh1D=ret3.retn();
9876 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9877 * (newly created) nodes corresponding to the edge intersections.
9879 * @param[out] cr, crI connectivity of the resulting mesh
9880 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9881 * TODO: describe input parameters
9883 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9884 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9885 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9886 const std::vector<double>& addCoords,
9887 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9889 static const int SPACEDIM=2;
9890 const double *coo1(m1->getCoords()->getConstPointer());
9891 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9892 int offset1(m1->getNumberOfNodes());
9893 const double *coo2(m2->getCoords()->getConstPointer());
9894 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9895 int offset2(offset1+m2->getNumberOfNodes());
9896 int offset3(offset2+((int)addCoords.size())/2);
9897 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9898 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9899 // Here a BBTree on 2D-cells, not on segments:
9900 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9901 int ncell1(m1->getNumberOfCells());
9903 for(int i=0;i<ncell1;i++)
9905 std::vector<int> candidates2;
9906 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9907 std::map<INTERP_KERNEL::Node *,int> mapp;
9908 std::map<int,INTERP_KERNEL::Node *> mappRev;
9909 INTERP_KERNEL::QuadraticPolygon pol1;
9910 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9911 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9912 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9913 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9914 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9915 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9916 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9918 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
9919 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9920 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9921 for(it1.first();!it1.finished();it1.next())
9922 edges1.insert(it1.current()->getPtr());
9924 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9925 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9927 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9929 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9930 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9931 // Complete mapping with elements coming from the current cell it2 in mesh2:
9932 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9933 // pol2 is the new QP in the final merged result.
9934 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9935 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9938 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9940 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9941 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9942 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9943 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9945 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9946 // by m2 but that we still want to keep in the final result.
9951 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9953 catch(INTERP_KERNEL::Exception& e)
9955 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();
9956 throw INTERP_KERNEL::Exception(oss.str().c_str());
9959 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9960 (*it).second->decrRef();
9965 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9966 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9967 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9968 * The caller is to deal with the resulting DataArrayInt.
9969 * \throw If the coordinate array is not set.
9970 * \throw If the nodal connectivity of the cells is not defined.
9971 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9972 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9974 * \sa DataArrayInt::sortEachPairToMakeALinkedList
9976 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9978 checkFullyDefined();
9979 if(getMeshDimension()!=1)
9980 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9982 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9984 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9985 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9986 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9987 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9989 const int * dsi(_dsi->getConstPointer());
9990 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9992 if (dsii->getNumberOfTuples())
9993 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9995 int nc(getNumberOfCells());
9996 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9997 result->alloc(nc,1);
9999 // set of edges not used so far
10000 std::set<int> edgeSet;
10001 for (int i=0; i<nc; edgeSet.insert(i), i++);
10005 // while we have points with only one neighbor segments
10008 std::list<int> linePiece;
10009 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10010 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10012 // Fill the list forward (resp. backward) from the start segment:
10013 int activeSeg = startSeg;
10014 int prevPointId = -20;
10016 while (!edgeSet.empty())
10018 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10021 linePiece.push_back(activeSeg);
10023 linePiece.push_front(activeSeg);
10024 edgeSet.erase(activeSeg);
10027 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10028 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10029 if (dsi[ptId] == 1) // hitting the end of the line
10031 prevPointId = ptId;
10032 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10033 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10036 // Done, save final piece into DA:
10037 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10038 newIdx += linePiece.size();
10040 // identify next valid start segment (one which is not consumed)
10041 if(!edgeSet.empty())
10042 startSeg = *(edgeSet.begin());
10044 while (!edgeSet.empty());
10045 return result.retn();
10050 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10052 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10053 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10055 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10056 int v((*it).second);
10057 if(v==forbVal0 || v==forbVal1)
10059 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10060 isect.push_back(v);
10063 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10068 bool presenceOfOn(false);
10069 for(int i=0;i<sz;i++)
10071 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10072 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10074 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10075 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10077 return presenceOfOn;
10083 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
10084 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
10085 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
10086 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10088 * \return int - the number of new nodes created (in most of cases 0).
10090 * \throw If \a this is not coherent.
10091 * \throw If \a this has not spaceDim equal to 2.
10092 * \throw If \a this has not meshDim equal to 2.
10093 * \throw If some subcells needed to be split are orphan.
10094 * \sa MEDCouplingUMesh::conformize2D
10096 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10098 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10099 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10100 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10101 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10102 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10103 if(midOpt==0 && midOptI==0)
10105 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10108 else if(midOpt!=0 && midOptI!=0)
10109 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10115 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10116 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10117 * 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
10118 * 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).
10119 * 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.
10121 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10122 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10124 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10125 * This method expects that all nodes in \a this are not closer than \a eps.
10126 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10128 * \param [in] eps the relative error to detect merged edges.
10129 * \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
10130 * that the user is expected to deal with.
10132 * \throw If \a this is not coherent.
10133 * \throw If \a this has not spaceDim equal to 2.
10134 * \throw If \a this has not meshDim equal to 2.
10135 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10137 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10139 static const int SPACEDIM=2;
10141 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10142 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10144 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10145 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10146 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10147 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10148 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10149 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10150 std::vector<double> addCoo;
10151 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10152 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10153 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10154 for(int i=0;i<nDescCell;i++)
10156 std::vector<int> candidates;
10157 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10158 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10161 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10162 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10163 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10164 INTERP_KERNEL::MergePoints merge;
10165 INTERP_KERNEL::QuadraticPolygon c1,c2;
10166 e1->intersectWith(e2,merge,c1,c2);
10167 e1->decrRef(); e2->decrRef();
10168 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10169 overlapEdge[i].push_back(*it);
10170 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10171 overlapEdge[*it].push_back(i);
10174 // splitting done. sort intersect point in intersectEdge.
10175 std::vector< std::vector<int> > middle(nDescCell);
10176 int nbOf2DCellsToBeSplit(0);
10177 bool middleNeedsToBeUsed(false);
10178 std::vector<bool> cells2DToTreat(nDescCell,false);
10179 for(int i=0;i<nDescCell;i++)
10181 std::vector<int>& isect(intersectEdge[i]);
10182 int sz((int)isect.size());
10185 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10186 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10187 e->sortSubNodesAbs(coords,isect);
10192 int idx0(rdi[i]),idx1(rdi[i+1]);
10194 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10195 if(!cells2DToTreat[rd[idx0]])
10197 cells2DToTreat[rd[idx0]]=true;
10198 nbOf2DCellsToBeSplit++;
10200 // try to reuse at most eventual 'middle' of SEG3
10201 std::vector<int>& mid(middle[i]);
10202 mid.resize(sz+1,-1);
10203 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10205 middleNeedsToBeUsed=true;
10206 const std::vector<int>& candidates(overlapEdge[i]);
10207 std::vector<int> trueCandidates;
10208 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10209 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10210 trueCandidates.push_back(*itc);
10211 int stNode(c[ci[i]+1]),endNode(isect[0]);
10212 for(int j=0;j<sz+1;j++)
10214 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10216 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10217 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10218 { mid[j]=*itc; break; }
10221 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10227 if(nbOf2DCellsToBeSplit==0)
10230 int *retPtr(ret->getPointer());
10231 for(int i=0;i<nCell;i++)
10232 if(cells2DToTreat[i])
10235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10236 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10237 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10238 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10239 if(middleNeedsToBeUsed)
10240 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10241 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10242 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10243 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.
10244 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10246 bool areNodesMerged; int newNbOfNodes;
10247 if(nbOfNodesCreated!=0)
10248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10254 * 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.
10255 * 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).
10256 * 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
10257 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10258 * 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
10259 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10261 * 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
10262 * using new instance, idem for coordinates.
10264 * 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.
10266 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10268 * \throw If \a this is not coherent.
10269 * \throw If \a this has not spaceDim equal to 2.
10270 * \throw If \a this has not meshDim equal to 2.
10272 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10274 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10278 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10279 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10280 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10281 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10282 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10283 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10285 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10286 const double *coords(_coords->begin());
10287 int *newciptr(newci->getPointer());
10288 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10290 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10291 ret->pushBackSilent(i);
10292 newciptr[1]=newc->getNumberOfTuples();
10297 if(!appendedCoords->empty())
10299 appendedCoords->rearrange(2);
10300 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10302 setCoords(newCoords);
10305 setConnectivity(newc,newci,true);
10310 * \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.
10311 * 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.
10312 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10313 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10314 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10315 * \param [out] addCoo - nodes to be append at the end
10316 * \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.
10318 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10319 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)
10321 static const int SPACEDIM=2;
10322 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10323 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10324 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10325 // Build BB tree of all edges in the tool mesh (second mesh)
10326 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10327 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10328 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10329 intersectEdge1.resize(nDescCell1);
10330 colinear2.resize(nDescCell2);
10331 subDiv2.resize(nDescCell2);
10332 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10334 std::vector<int> candidates1(1);
10335 int offset1(m1Desc->getNumberOfNodes());
10336 int offset2(offset1+m2Desc->getNumberOfNodes());
10337 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10339 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10340 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10341 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10343 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10344 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10345 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10347 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10348 // 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
10349 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10350 std::set<INTERP_KERNEL::Node *> nodes;
10351 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10352 std::size_t szz(nodes.size());
10353 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10354 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10355 for(std::size_t iii=0;iii<szz;iii++,itt++)
10356 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10357 // end of protection
10358 // Performs egde cutting:
10359 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10364 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10365 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10370 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10371 * It builds the descending connectivity of the two meshes, and then using a binary tree
10372 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10373 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10375 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10376 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10377 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10378 std::vector<double>& addCoo,
10379 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10381 // Build desc connectivity
10382 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10383 desc2=DataArrayInt::New();
10384 descIndx2=DataArrayInt::New();
10385 revDesc2=DataArrayInt::New();
10386 revDescIndx2=DataArrayInt::New();
10387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10389 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10390 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10391 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10392 std::map<int,int> notUsedMap;
10393 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10394 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10395 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10399 * This method performs the 2nd step of Partition of 2D mesh.
10400 * This method has 4 inputs :
10401 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10402 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10403 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10404 * 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'
10405 * Nodes end up lying consecutively on a cutted edge.
10406 * \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.
10407 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10408 * \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.
10409 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10410 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10412 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10413 const std::vector<double>& addCoo,
10414 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10416 int offset1=m1->getNumberOfNodes();
10417 int ncell=m2->getNumberOfCells();
10418 const int *c=m2->getNodalConnectivity()->getConstPointer();
10419 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10420 const double *coo=m2->getCoords()->getConstPointer();
10421 const double *cooBis=m1->getCoords()->getConstPointer();
10422 int offset2=offset1+m2->getNumberOfNodes();
10423 intersectEdge.resize(ncell);
10424 for(int i=0;i<ncell;i++,cI++)
10426 const std::vector<int>& divs=subDiv[i];
10427 int nnode=cI[1]-cI[0]-1;
10428 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10429 std::map<INTERP_KERNEL::Node *, int> mapp22;
10430 for(int j=0;j<nnode;j++)
10432 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10433 int nnid=c[(*cI)+j+1];
10434 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10435 mapp22[nn]=nnid+offset1;
10437 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10438 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10439 ((*it).second.first)->decrRef();
10440 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10441 std::map<INTERP_KERNEL::Node *,int> mapp3;
10442 for(std::size_t j=0;j<divs.size();j++)
10445 INTERP_KERNEL::Node *tmp=0;
10447 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10448 else if(id<offset2)
10449 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10451 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10455 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10456 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10463 * 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).
10464 * 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
10465 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10466 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10467 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10468 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10469 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10470 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10471 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10472 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10473 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10474 * \param [out] cut3DSuf input/output param.
10476 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10477 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10478 const int *desc, const int *descIndx,
10479 std::vector< std::pair<int,int> >& cut3DSurf)
10481 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10482 int nbOf3DSurfCell=(int)cut3DSurf.size();
10483 for(int i=0;i<nbOf3DSurfCell;i++)
10485 std::vector<int> res;
10486 int offset=descIndx[i];
10487 int nbOfSeg=descIndx[i+1]-offset;
10488 for(int j=0;j<nbOfSeg;j++)
10490 int edgeId=desc[offset+j];
10491 int status=cut3DCurve[edgeId];
10495 res.push_back(status);
10498 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10499 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10507 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10513 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10514 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10517 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10521 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10526 {// case when plane is on a multi colinear edge of a polyhedron
10527 if((int)res.size()==2*nbOfSeg)
10529 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10532 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10539 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10540 * 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).
10541 * 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
10542 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10543 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10544 * \param desc is the descending connectivity 3D->3DSurf
10545 * \param descIndx is the descending connectivity index 3D->3DSurf
10547 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10548 const int *desc, const int *descIndx,
10549 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10551 checkFullyDefined();
10552 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10553 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10554 const int *nodal3D=_nodal_connec->getConstPointer();
10555 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10556 int nbOfCells=getNumberOfCells();
10557 for(int i=0;i<nbOfCells;i++)
10559 std::map<int, std::set<int> > m;
10560 int offset=descIndx[i];
10561 int nbOfFaces=descIndx[i+1]-offset;
10564 for(int j=0;j<nbOfFaces;j++)
10566 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10567 if(p.first!=-1 && p.second!=-1)
10571 start=p.first; end=p.second;
10572 m[p.first].insert(p.second);
10573 m[p.second].insert(p.first);
10577 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10578 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10579 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10580 INTERP_KERNEL::NormalizedCellType cmsId;
10581 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10582 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10583 for(unsigned k=0;k<nbOfNodesSon;k++)
10585 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10586 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10593 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10597 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10598 const std::set<int>& s=(*it).second;
10599 std::set<int> s2; s2.insert(prev);
10601 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10604 int val=*s3.begin();
10605 conn.push_back(start);
10612 conn.push_back(end);
10615 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10616 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10617 cellIds->pushBackSilent(i);
10623 * 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
10624 * 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
10625 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10626 * 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
10627 * 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.
10629 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10631 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10633 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10636 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10637 if(cm.getDimension()==2)
10639 const int *node=nodalConnBg+1;
10640 int startNode=*node++;
10641 double refX=coords[2*startNode];
10642 for(;node!=nodalConnEnd;node++)
10644 if(coords[2*(*node)]<refX)
10647 refX=coords[2*startNode];
10650 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10654 double angle0=-M_PI/2;
10659 double angleNext=0.;
10660 while(nextNode!=startNode)
10664 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10666 if(*node!=tmpOut.back() && *node!=prevNode)
10668 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10669 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10674 res=angle0-angleM+2.*M_PI;
10683 if(nextNode!=startNode)
10685 angle0=angleNext-M_PI;
10688 prevNode=tmpOut.back();
10689 tmpOut.push_back(nextNode);
10692 std::vector<int> tmp3(2*(sz-1));
10693 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10694 std::copy(nodalConnBg+1,nodalConnEnd,it);
10695 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10697 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10700 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10702 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10707 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10708 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10720 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10721 * 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.
10723 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10724 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10725 * \param [in,out] arr array in which the remove operation will be done.
10726 * \param [in,out] arrIndx array in the remove operation will modify
10727 * \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])
10728 * \return true if \b arr and \b arrIndx have been modified, false if not.
10730 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10732 if(!arrIndx || !arr)
10733 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10734 if(offsetForRemoval<0)
10735 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10736 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10737 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10738 int *arrIPtr=arrIndx->getPointer();
10740 int previousArrI=0;
10741 const int *arrPtr=arr->getConstPointer();
10742 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10743 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10745 if(*arrIPtr-previousArrI>offsetForRemoval)
10747 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10749 if(s.find(*work)==s.end())
10750 arrOut.push_back(*work);
10753 previousArrI=*arrIPtr;
10754 *arrIPtr=(int)arrOut.size();
10756 if(arr->getNumberOfTuples()==(int)arrOut.size())
10758 arr->alloc((int)arrOut.size(),1);
10759 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10764 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10765 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10766 * The selection of extraction is done standardly in new2old format.
10767 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10769 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10770 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10771 * \param [in] arrIn arr origin array from which the extraction will be done.
10772 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10773 * \param [out] arrOut the resulting array
10774 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10775 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10777 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10778 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10780 if(!arrIn || !arrIndxIn)
10781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10782 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10783 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10784 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10785 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10786 const int *arrInPtr=arrIn->getConstPointer();
10787 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10788 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10791 int maxSizeOfArr=arrIn->getNumberOfTuples();
10792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10793 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10794 arrIo->alloc((int)(sz+1),1);
10795 const int *idsIt=idsOfSelectBg;
10796 int *work=arrIo->getPointer();
10799 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10801 if(*idsIt>=0 && *idsIt<nbOfGrps)
10802 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10805 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10806 throw INTERP_KERNEL::Exception(oss.str().c_str());
10812 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10813 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10814 throw INTERP_KERNEL::Exception(oss.str().c_str());
10817 arro->alloc(lgth,1);
10818 work=arro->getPointer();
10819 idsIt=idsOfSelectBg;
10820 for(std::size_t i=0;i<sz;i++,idsIt++)
10822 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10823 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10826 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10827 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10828 throw INTERP_KERNEL::Exception(oss.str().c_str());
10831 arrOut=arro.retn();
10832 arrIndexOut=arrIo.retn();
10836 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10837 * 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 ).
10838 * The selection of extraction is done standardly in new2old format.
10839 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10841 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10842 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10843 * \param [in] arrIn arr origin array from which the extraction will be done.
10844 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10845 * \param [out] arrOut the resulting array
10846 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10847 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10849 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10850 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10852 if(!arrIn || !arrIndxIn)
10853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10854 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10855 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10856 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10857 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10858 const int *arrInPtr=arrIn->getConstPointer();
10859 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10860 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10862 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10863 int maxSizeOfArr=arrIn->getNumberOfTuples();
10864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10866 arrIo->alloc((int)(sz+1),1);
10867 int idsIt=idsOfSelectStart;
10868 int *work=arrIo->getPointer();
10871 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10873 if(idsIt>=0 && idsIt<nbOfGrps)
10874 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10877 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10878 throw INTERP_KERNEL::Exception(oss.str().c_str());
10884 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10885 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10886 throw INTERP_KERNEL::Exception(oss.str().c_str());
10889 arro->alloc(lgth,1);
10890 work=arro->getPointer();
10891 idsIt=idsOfSelectStart;
10892 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10894 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10895 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10898 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10899 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10900 throw INTERP_KERNEL::Exception(oss.str().c_str());
10903 arrOut=arro.retn();
10904 arrIndexOut=arrIo.retn();
10908 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10909 * 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
10910 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10911 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10913 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10914 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10915 * \param [in] arrIn arr origin array from which the extraction will be done.
10916 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10917 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10918 * \param [in] srcArrIndex index array of \b srcArr
10919 * \param [out] arrOut the resulting array
10920 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10922 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10924 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10925 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10926 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10928 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10929 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10930 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10931 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10932 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10933 std::vector<bool> v(nbOfTuples,true);
10935 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10936 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10937 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10939 if(*it>=0 && *it<nbOfTuples)
10942 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10946 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10947 throw INTERP_KERNEL::Exception(oss.str().c_str());
10950 srcArrIndexPtr=srcArrIndex->getConstPointer();
10951 arrIo->alloc(nbOfTuples+1,1);
10952 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10953 const int *arrInPtr=arrIn->getConstPointer();
10954 const int *srcArrPtr=srcArr->getConstPointer();
10955 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10956 int *arroPtr=arro->getPointer();
10957 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10961 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10962 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10966 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10967 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10968 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10971 arrOut=arro.retn();
10972 arrIndexOut=arrIo.retn();
10976 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10977 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10979 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10980 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10981 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10982 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10983 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10984 * \param [in] srcArrIndex index array of \b srcArr
10986 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10988 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10989 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10991 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10992 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10993 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10994 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10995 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10996 int *arrInOutPtr=arrInOut->getPointer();
10997 const int *srcArrPtr=srcArr->getConstPointer();
10998 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11000 if(*it>=0 && *it<nbOfTuples)
11002 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11003 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11006 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] !";
11007 throw INTERP_KERNEL::Exception(oss.str().c_str());
11012 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11013 throw INTERP_KERNEL::Exception(oss.str().c_str());
11019 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11020 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11021 * 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]].
11022 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11023 * A negative value in \b arrIn means that it is ignored.
11024 * 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.
11026 * \param [in] arrIn arr origin array from which the extraction will be done.
11027 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11028 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11029 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11031 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11033 int seed=0,nbOfDepthPeelingPerformed=0;
11034 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11038 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11039 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11040 * 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]].
11041 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11042 * A negative value in \b arrIn means that it is ignored.
11043 * 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.
11044 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11045 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11046 * \param [in] arrIn arr origin array from which the extraction will be done.
11047 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11048 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11049 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11050 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11051 * \sa MEDCouplingUMesh::partitionBySpreadZone
11053 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11055 nbOfDepthPeelingPerformed=0;
11057 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11058 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11061 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11065 std::vector<bool> fetched(nbOfTuples,false);
11066 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11069 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11071 nbOfDepthPeelingPerformed=0;
11072 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11073 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11074 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11075 std::vector<bool> fetched2(nbOfTuples,false);
11077 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11079 if(*seedElt>=0 && *seedElt<nbOfTuples)
11080 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11082 { 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()); }
11084 const int *arrInPtr=arrIn->getConstPointer();
11085 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11086 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11087 std::vector<int> idsToFetch1(seedBg,seedEnd);
11088 std::vector<int> idsToFetch2;
11089 std::vector<int> *idsToFetch=&idsToFetch1;
11090 std::vector<int> *idsToFetchOther=&idsToFetch2;
11091 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11093 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11094 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11096 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11097 std::swap(idsToFetch,idsToFetchOther);
11098 idsToFetchOther->clear();
11099 nbOfDepthPeelingPerformed++;
11101 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11104 int *retPtr=ret->getPointer();
11105 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11112 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11113 * 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
11114 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11115 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11117 * \param [in] start begin of set of ids of the input extraction (included)
11118 * \param [in] end end of set of ids of the input extraction (excluded)
11119 * \param [in] step step of the set of ids in range mode.
11120 * \param [in] arrIn arr origin array from which the extraction will be done.
11121 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11122 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11123 * \param [in] srcArrIndex index array of \b srcArr
11124 * \param [out] arrOut the resulting array
11125 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11127 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11129 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11130 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11131 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11133 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11134 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11137 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11139 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11140 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11141 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11143 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11145 if(it>=0 && it<nbOfTuples)
11146 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11149 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11150 throw INTERP_KERNEL::Exception(oss.str().c_str());
11153 srcArrIndexPtr=srcArrIndex->getConstPointer();
11154 arrIo->alloc(nbOfTuples+1,1);
11155 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11156 const int *arrInPtr=arrIn->getConstPointer();
11157 const int *srcArrPtr=srcArr->getConstPointer();
11158 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11159 int *arroPtr=arro->getPointer();
11160 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11162 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11165 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11166 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11170 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11171 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11174 arrOut=arro.retn();
11175 arrIndexOut=arrIo.retn();
11179 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11180 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11182 * \param [in] start begin of set of ids of the input extraction (included)
11183 * \param [in] end end of set of ids of the input extraction (excluded)
11184 * \param [in] step step of the set of ids in range mode.
11185 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11186 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11187 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11188 * \param [in] srcArrIndex index array of \b srcArr
11190 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11192 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11193 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11195 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11196 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11197 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11198 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11199 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11200 int *arrInOutPtr=arrInOut->getPointer();
11201 const int *srcArrPtr=srcArr->getConstPointer();
11202 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11204 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11206 if(it>=0 && it<nbOfTuples)
11208 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11209 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11212 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11213 throw INTERP_KERNEL::Exception(oss.str().c_str());
11218 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11219 throw INTERP_KERNEL::Exception(oss.str().c_str());
11225 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11226 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11227 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11228 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11229 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11231 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11233 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11235 checkFullyDefined();
11236 int mdim=getMeshDimension();
11237 int spaceDim=getSpaceDimension();
11239 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11240 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11241 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11242 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11243 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11244 ret->setCoords(getCoords());
11245 ret->allocateCells((int)partition.size());
11247 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11249 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11254 cell=tmp->buildUnionOf2DMesh();
11257 cell=tmp->buildUnionOf3DMesh();
11260 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11263 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11266 ret->finishInsertingCells();
11271 * This method partitions \b this into contiguous zone.
11272 * This method only needs a well defined connectivity. Coordinates are not considered here.
11273 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11275 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11277 int nbOfCellsCur=getNumberOfCells();
11278 std::vector<DataArrayInt *> ret;
11279 if(nbOfCellsCur<=0)
11281 DataArrayInt *neigh=0,*neighI=0;
11282 computeNeighborsOfCells(neigh,neighI);
11283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11284 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11285 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11287 while(seed<nbOfCellsCur)
11289 int nbOfPeelPerformed=0;
11290 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11291 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11293 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11294 ret.push_back((*it).retn());
11299 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11300 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11302 * \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.
11303 * \return a newly allocated DataArrayInt to be managed by the caller.
11304 * \throw In case of \a code has not the right format (typically of size 3*n)
11306 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11309 std::size_t nb=code.size()/3;
11310 if(code.size()%3!=0)
11311 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11312 ret->alloc((int)nb,2);
11313 int *retPtr=ret->getPointer();
11314 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11316 retPtr[0]=code[3*i+2];
11317 retPtr[1]=code[3*i+2]+code[3*i+1];
11323 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11324 * All cells in \a this are expected to be linear 3D cells.
11325 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11326 * It leads to an increase to number of cells.
11327 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11328 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11329 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11331 * \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.
11332 * For all other cells, the splitting policy will be ignored.
11333 * \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.
11334 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11335 * an id of old cell producing it. The caller is to delete this array using
11336 * decrRef() as it is no more needed.
11337 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11339 * \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
11340 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11342 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11343 * \throw If \a this is not fully constituted with linear 3D cells.
11344 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11346 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11348 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11349 checkConnectivityFullyDefined();
11350 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11351 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11352 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11353 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11355 int *retPt(ret->getPointer());
11356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11357 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11358 const int *oldc(_nodal_connec->begin());
11359 const int *oldci(_nodal_connec_index->begin());
11360 const double *coords(_coords->begin());
11361 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11363 std::vector<int> a; std::vector<double> b;
11364 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11365 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11366 const int *aa(&a[0]);
11369 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11371 *it=(-(*(it))-1+nbNodes);
11372 addPts->insertAtTheEnd(b.begin(),b.end());
11373 nbNodes+=(int)b.size()/3;
11375 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11376 newConn->insertAtTheEnd(aa,aa+4);
11378 if(!addPts->empty())
11380 addPts->rearrange(3);
11381 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11382 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11383 ret0->setCoords(addPts);
11387 nbOfAdditionalPoints=0;
11388 ret0->setCoords(getCoords());
11390 ret0->setNodalConnectivity(newConn);
11392 ret->computeOffsets2();
11393 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11394 return ret0.retn();
11398 * 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).
11400 * \sa MEDCouplingUMesh::split2DCells
11402 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11404 checkConnectivityFullyDefined();
11405 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11407 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11408 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11409 int prevPosOfCi(ciPtr[0]);
11410 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11412 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11413 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11414 for(int j=0;j<sz;j++)
11416 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11417 for(int k=0;k<sz2;k++)
11418 *cPtr++=subPtr[offset2+k];
11420 *cPtr++=oldConn[prevPosOfCi+j+2];
11423 prevPosOfCi=ciPtr[1];
11424 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11428 _nodal_connec->decrRef();
11429 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11432 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11438 int ret(nodesCnter++);
11440 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11441 addCoo.insertAtTheEnd(newPt,newPt+2);
11446 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11452 int ret(nodesCnter++);
11454 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11455 addCoo.insertAtTheEnd(newPt,newPt+2);
11463 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)
11466 int trueStart(start>=0?start:nbOfEdges+start);
11467 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11468 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11473 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11474 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11475 middles.push_back(tmp3+offset);
11478 middles.push_back(connBg[trueStart+nbOfEdges]);
11482 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)
11484 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11485 newConnOfCell->pushBackSilent(tmpEnd);
11490 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11491 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11492 middles.push_back(tmp3+offset);
11495 middles.push_back(connBg[start+nbOfEdges]);
11499 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)
11501 // only the quadratic point to deal with:
11506 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11507 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11508 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11509 middles.push_back(tmp3+offset);
11512 middles.push_back(connBg[start+nbOfEdges]);
11519 * 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 ) .
11520 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11522 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11524 std::size_t sz(std::distance(connBg,connEnd));
11525 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11526 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11528 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11529 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11530 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11531 unsigned nbOfHit(0); // number of fusions operated
11532 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11533 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
11534 INTERP_KERNEL::NormalizedCellType typeOfSon;
11535 std::vector<int> middles;
11537 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11539 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11540 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11541 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11542 posEndElt = posBaseElt+1;
11544 // Look backward first: are the final edges of the cells colinear with the first ones?
11545 // This initializes posBaseElt.
11548 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11550 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11551 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11552 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11553 bool isColinear=eint->areColinears();
11566 // Now move forward:
11567 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11568 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11570 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11571 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11572 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11573 bool isColinear(eint->areColinears());
11585 //push [posBaseElt,posEndElt) in newConnOfCell using e
11586 // 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!
11588 // at the begining of the connectivity (insert type)
11589 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11590 else if((nbOfHit+nbOfTurn) != (nbs-1))
11592 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11593 if ((nbOfHit+nbOfTurn) == (nbs-1))
11594 // at the end (only quad points to deal with)
11595 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11596 posBaseElt=posEndElt;
11599 if(!middles.empty())
11600 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11605 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11607 * \return int - the number of new nodes created.
11608 * \sa MEDCouplingUMesh::split2DCells
11610 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11613 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11614 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11615 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11616 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11617 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11618 const double *oldCoordsPtr(getCoords()->begin());
11619 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11620 int prevPosOfCi(ciPtr[0]);
11621 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11623 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11624 for(int j=0;j<sz;j++)
11625 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11626 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11627 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11629 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11633 cPtr[1]=oldConn[prevPosOfCi+2+j];
11634 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11637 std::vector<INTERP_KERNEL::Node *> ns(3);
11638 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11639 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11640 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11641 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11642 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11644 cPtr[1]=subPtr[offset2+k];
11645 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11647 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11649 { cPtr[1]=tmpEnd; }
11650 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11652 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11653 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11657 _nodal_connec->decrRef();
11658 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11659 addCoo->rearrange(2);
11660 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11662 return addCoo->getNumberOfTuples();
11665 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11667 if(nodalConnec && nodalConnecIndex)
11670 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11671 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11673 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11674 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11678 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11679 _own_cell(true),_cell_id(-1),_nb_cell(0)
11684 _nb_cell=mesh->getNumberOfCells();
11688 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11696 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11697 _own_cell(false),_cell_id(bg-1),
11704 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11707 if(_cell_id<_nb_cell)
11716 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11722 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11724 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11727 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11733 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11741 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11747 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11752 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11757 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11759 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11762 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11767 _nb_cell=mesh->getNumberOfCells();
11771 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11778 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11780 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11781 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11782 if(_cell_id<_nb_cell)
11784 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11785 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11786 int startId=_cell_id;
11787 _cell_id+=nbOfElems;
11788 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11794 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11798 _conn=mesh->getNodalConnectivity()->getPointer();
11799 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11803 void MEDCouplingUMeshCell::next()
11805 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11810 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11813 std::string MEDCouplingUMeshCell::repr() const
11815 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11817 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11819 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11823 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11826 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11828 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11829 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11831 return INTERP_KERNEL::NORM_ERROR;
11834 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11837 if(_conn_lgth!=NOTICABLE_FIRST_VAL)